Skip to content
File

Blob: src/workerd/api/crypto/keys.h

cpp140 lines
1#pragma once
2 
3#include "impl.h"
4 
5namespace workerd::api {
6 
7enum class KeyEncoding {
8 PKCS1,
9 PKCS8,
10 SPKI,
11 SEC1,
12};
13 
14inline kj::StringPtr KJ_STRINGIFY(KeyEncoding encoding) {
15 switch (encoding) {
16 case KeyEncoding::PKCS1:
17 return "pkcs1";
18 case KeyEncoding::PKCS8:
19 return "pkcs8";
20 case KeyEncoding::SPKI:
21 return "spki";
22 case KeyEncoding::SEC1:
23 return "sec1";
24 }
25 KJ_UNREACHABLE;
26}
27 
28enum class KeyFormat {
29 PEM,
30 DER,
31 JWK,
32};
33 
34enum class KeyType {
35 SECRET,
36 PUBLIC,
37 PRIVATE,
38};
39 
40kj::StringPtr toStringPtr(KeyType type);
41 
42struct AsymmetricKeyData {
43 kj::Own<EVP_PKEY> evpPkey;
44 KeyType keyType;
45 CryptoKeyUsageSet usages;
46};
47 
48class AsymmetricKeyCryptoKeyImpl: public CryptoKey::Impl {
49 public:
50 explicit AsymmetricKeyCryptoKeyImpl(AsymmetricKeyData&& key, bool extractable);
51 
52 // ---------------------------------------------------------------------------
53 // Subclasses must implement these
54 
55 // virtual CryptoKey::AlgorithmVariant getAlgorithm() = 0;
56 // kj::StringPtr getAlgorithmName() const = 0;
57 // (inherited from CryptoKey::Impl, needs to be implemented by subclass)
58 
59 // Determine the hash function to use. Some algorithms choose this at key import time while
60 // others choose it at sign() or verify() time. `callTimeHash` is the hash name passed to the
61 // call.
62 virtual kj::StringPtr chooseHash(
63 const kj::Maybe<kj::OneOf<kj::String, SubtleCrypto::HashAlgorithm>>& callTimeHash) const = 0;
64 
65 // Convert OpenSSL-format signature to WebCrypto-format signature, if different.
66 virtual jsg::JsArrayBuffer signatureSslToWebCrypto(
67 jsg::Lock& js, kj::ArrayPtr<kj::byte> signature) const;
68 
69 // Convert WebCrypto-format signature to OpenSSL-format signature, if different.
70 virtual jsg::JsArrayBuffer signatureWebCryptoToSsl(
71 jsg::Lock& js, kj::ArrayPtr<const kj::byte> signature) const;
72 
73 // Add salt to digest context in order to generate or verify salted signature.
74 // Currently only used for RSA-PSS sign and verify operations.
75 virtual void addSalt(
76 EVP_PKEY_CTX* digestCtx, const SubtleCrypto::SignAlgorithm& algorithm) const {}
77 
78 // ---------------------------------------------------------------------------
79 // Implementation of CryptoKey
80 
81 SubtleCrypto::ExportKeyData exportKey(jsg::Lock& js, kj::StringPtr format) const override final;
82 
83 virtual jsg::JsUint8Array exportKeyExt(jsg::Lock& js,
84 kj::StringPtr format,
85 kj::StringPtr type,
86 jsg::Optional<kj::String> cipher = kj::none,
87 jsg::Optional<kj::Array<kj::byte>> passphrase = kj::none) const override final;
88 
89 jsg::JsArrayBuffer sign(jsg::Lock& js,
90 SubtleCrypto::SignAlgorithm&& algorithm,
91 kj::ArrayPtr<const kj::byte> data) const override;
92 
93 bool verify(jsg::Lock& js,
94 SubtleCrypto::SignAlgorithm&& algorithm,
95 kj::ArrayPtr<const kj::byte> signature,
96 kj::ArrayPtr<const kj::byte> data) const override;
97 
98 kj::StringPtr getType() const override;
99 KeyType getTypeEnum() const {
100 return keyType;
101 }
102 
103 inline EVP_PKEY* getEvpPkey() const {
104 return keyData.get();
105 }
106 
107 bool equals(const CryptoKey::Impl& other) const override final;
108 
109 kj::StringPtr jsgGetMemoryName() const override {
110 return "AsymmetricKey";
111 }
112 size_t jsgGetMemorySelfSize() const override {
113 return sizeof(AsymmetricKeyCryptoKeyImpl);
114 }
115 void jsgGetMemoryInfo(jsg::MemoryTracker& tracker) const override {}
116 
117 bool verifyX509Public(const X509* cert) const override;
118 bool verifyX509Private(const X509* cert) const override;
119 
120 private:
121 virtual SubtleCrypto::JsonWebKey exportJwk() const = 0;
122 virtual jsg::JsArrayBuffer exportRaw(jsg::Lock& js) const = 0;
123 
124 mutable kj::Own<EVP_PKEY> keyData;
125 // mutable because OpenSSL wants non-const pointers even when the object won't be modified...
126 KeyType keyType;
127};
128 
129// Performs asymmetric key import per the Web Crypto spec.
130AsymmetricKeyData importAsymmetricForWebCrypto(jsg::Lock& js,
131 kj::StringPtr format,
132 SubtleCrypto::ImportKeyData keyData,
133 kj::StringPtr normalizedName,
134 bool extractable,
135 kj::ArrayPtr<const kj::String> keyUsages,
136 kj::FunctionParam<kj::Own<EVP_PKEY>(SubtleCrypto::JsonWebKey)> readJwk,
137 CryptoKeyUsageSet allowedUsages);
138 
139} // namespace workerd::api