File
Blob: src/workerd/api/crypto/keys.h
| 1 | #pragma once |
| 2 | |
| 3 | #include "impl.h" |
| 4 | |
| 5 | namespace workerd::api { |
| 6 | |
| 7 | enum class KeyEncoding { |
| 8 | PKCS1, |
| 9 | PKCS8, |
| 10 | SPKI, |
| 11 | SEC1, |
| 12 | }; |
| 13 | |
| 14 | inline 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 | |
| 28 | enum class KeyFormat { |
| 29 | PEM, |
| 30 | DER, |
| 31 | JWK, |
| 32 | }; |
| 33 | |
| 34 | enum class KeyType { |
| 35 | SECRET, |
| 36 | PUBLIC, |
| 37 | PRIVATE, |
| 38 | }; |
| 39 | |
| 40 | kj::StringPtr toStringPtr(KeyType type); |
| 41 | |
| 42 | struct AsymmetricKeyData { |
| 43 | kj::Own<EVP_PKEY> evpPkey; |
| 44 | KeyType keyType; |
| 45 | CryptoKeyUsageSet usages; |
| 46 | }; |
| 47 | |
| 48 | class 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. |
| 130 | AsymmetricKeyData 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 |