summaryrefslogtreecommitdiffstats
path: root/dom/crypto/WebCryptoCommon.h
diff options
context:
space:
mode:
Diffstat (limited to 'dom/crypto/WebCryptoCommon.h')
-rw-r--r--dom/crypto/WebCryptoCommon.h352
1 files changed, 352 insertions, 0 deletions
diff --git a/dom/crypto/WebCryptoCommon.h b/dom/crypto/WebCryptoCommon.h
new file mode 100644
index 000000000..8eb5c20e1
--- /dev/null
+++ b/dom/crypto/WebCryptoCommon.h
@@ -0,0 +1,352 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_WebCryptoCommon_h
+#define mozilla_dom_WebCryptoCommon_h
+
+#include "js/StructuredClone.h"
+#include "mozilla/ArrayUtils.h"
+#include "mozilla/dom/CryptoBuffer.h"
+#include "nsContentUtils.h"
+#include "nsString.h"
+#include "pk11pub.h"
+
+// WebCrypto algorithm names
+#define WEBCRYPTO_ALG_AES_CBC "AES-CBC"
+#define WEBCRYPTO_ALG_AES_CTR "AES-CTR"
+#define WEBCRYPTO_ALG_AES_GCM "AES-GCM"
+#define WEBCRYPTO_ALG_AES_KW "AES-KW"
+#define WEBCRYPTO_ALG_SHA1 "SHA-1"
+#define WEBCRYPTO_ALG_SHA256 "SHA-256"
+#define WEBCRYPTO_ALG_SHA384 "SHA-384"
+#define WEBCRYPTO_ALG_SHA512 "SHA-512"
+#define WEBCRYPTO_ALG_HMAC "HMAC"
+#define WEBCRYPTO_ALG_HKDF "HKDF"
+#define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
+#define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
+#define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
+#define WEBCRYPTO_ALG_RSA_PSS "RSA-PSS"
+#define WEBCRYPTO_ALG_ECDH "ECDH"
+#define WEBCRYPTO_ALG_ECDSA "ECDSA"
+#define WEBCRYPTO_ALG_DH "DH"
+
+// WebCrypto key formats
+#define WEBCRYPTO_KEY_FORMAT_RAW "raw"
+#define WEBCRYPTO_KEY_FORMAT_PKCS8 "pkcs8"
+#define WEBCRYPTO_KEY_FORMAT_SPKI "spki"
+#define WEBCRYPTO_KEY_FORMAT_JWK "jwk"
+
+// WebCrypto key types
+#define WEBCRYPTO_KEY_TYPE_PUBLIC "public"
+#define WEBCRYPTO_KEY_TYPE_PRIVATE "private"
+#define WEBCRYPTO_KEY_TYPE_SECRET "secret"
+
+// WebCrypto key usages
+#define WEBCRYPTO_KEY_USAGE_ENCRYPT "encrypt"
+#define WEBCRYPTO_KEY_USAGE_DECRYPT "decrypt"
+#define WEBCRYPTO_KEY_USAGE_SIGN "sign"
+#define WEBCRYPTO_KEY_USAGE_VERIFY "verify"
+#define WEBCRYPTO_KEY_USAGE_DERIVEKEY "deriveKey"
+#define WEBCRYPTO_KEY_USAGE_DERIVEBITS "deriveBits"
+#define WEBCRYPTO_KEY_USAGE_WRAPKEY "wrapKey"
+#define WEBCRYPTO_KEY_USAGE_UNWRAPKEY "unwrapKey"
+
+// WebCrypto named curves
+#define WEBCRYPTO_NAMED_CURVE_P256 "P-256"
+#define WEBCRYPTO_NAMED_CURVE_P384 "P-384"
+#define WEBCRYPTO_NAMED_CURVE_P521 "P-521"
+
+// JWK key types
+#define JWK_TYPE_SYMMETRIC "oct"
+#define JWK_TYPE_RSA "RSA"
+#define JWK_TYPE_EC "EC"
+
+// JWK algorithms
+#define JWK_ALG_A128CBC "A128CBC" // CBC
+#define JWK_ALG_A192CBC "A192CBC"
+#define JWK_ALG_A256CBC "A256CBC"
+#define JWK_ALG_A128CTR "A128CTR" // CTR
+#define JWK_ALG_A192CTR "A192CTR"
+#define JWK_ALG_A256CTR "A256CTR"
+#define JWK_ALG_A128GCM "A128GCM" // GCM
+#define JWK_ALG_A192GCM "A192GCM"
+#define JWK_ALG_A256GCM "A256GCM"
+#define JWK_ALG_A128KW "A128KW" // KW
+#define JWK_ALG_A192KW "A192KW"
+#define JWK_ALG_A256KW "A256KW"
+#define JWK_ALG_HS1 "HS1" // HMAC
+#define JWK_ALG_HS256 "HS256"
+#define JWK_ALG_HS384 "HS384"
+#define JWK_ALG_HS512 "HS512"
+#define JWK_ALG_RS1 "RS1" // RSASSA-PKCS1
+#define JWK_ALG_RS256 "RS256"
+#define JWK_ALG_RS384 "RS384"
+#define JWK_ALG_RS512 "RS512"
+#define JWK_ALG_RSA_OAEP "RSA-OAEP" // RSA-OAEP
+#define JWK_ALG_RSA_OAEP_256 "RSA-OAEP-256"
+#define JWK_ALG_RSA_OAEP_384 "RSA-OAEP-384"
+#define JWK_ALG_RSA_OAEP_512 "RSA-OAEP-512"
+#define JWK_ALG_PS1 "PS1" // RSA-PSS
+#define JWK_ALG_PS256 "PS256"
+#define JWK_ALG_PS384 "PS384"
+#define JWK_ALG_PS512 "PS512"
+#define JWK_ALG_ECDSA_P_256 "ES256"
+#define JWK_ALG_ECDSA_P_384 "ES384"
+#define JWK_ALG_ECDSA_P_521 "ES521"
+
+// JWK usages
+#define JWK_USE_ENC "enc"
+#define JWK_USE_SIG "sig"
+
+// Define an unknown mechanism type
+#define UNKNOWN_CK_MECHANISM CKM_VENDOR_DEFINED+1
+
+// python security/pkix/tools/DottedOIDToCode.py id-ecDH 1.3.132.112
+static const uint8_t id_ecDH[] = { 0x2b, 0x81, 0x04, 0x70 };
+const SECItem SEC_OID_DATA_EC_DH = { siBuffer, (unsigned char*)id_ecDH,
+ static_cast<unsigned int>(
+ mozilla::ArrayLength(id_ecDH)) };
+
+// python security/pkix/tools/DottedOIDToCode.py dhKeyAgreement 1.2.840.113549.1.3.1
+static const uint8_t dhKeyAgreement[] = {
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03, 0x01
+};
+const SECItem SEC_OID_DATA_DH_KEY_AGREEMENT = { siBuffer,
+ (unsigned char*)dhKeyAgreement,
+ static_cast<unsigned int>(
+ mozilla::ArrayLength(dhKeyAgreement)) };
+
+namespace mozilla {
+namespace dom {
+
+// Helper functions for structured cloning
+inline bool
+ReadString(JSStructuredCloneReader* aReader, nsString& aString)
+{
+ bool read;
+ uint32_t nameLength, zero;
+ read = JS_ReadUint32Pair(aReader, &nameLength, &zero);
+ if (!read) {
+ return false;
+ }
+
+ aString.SetLength(nameLength);
+ size_t charSize = sizeof(nsString::char_type);
+ read = JS_ReadBytes(aReader, (void*) aString.BeginWriting(), nameLength * charSize);
+ if (!read) {
+ return false;
+ }
+
+ return true;
+}
+
+inline bool
+WriteString(JSStructuredCloneWriter* aWriter, const nsString& aString)
+{
+ size_t charSize = sizeof(nsString::char_type);
+ return JS_WriteUint32Pair(aWriter, aString.Length(), 0) &&
+ JS_WriteBytes(aWriter, aString.get(), aString.Length() * charSize);
+}
+
+inline bool
+ReadBuffer(JSStructuredCloneReader* aReader, CryptoBuffer& aBuffer)
+{
+ uint32_t length, zero;
+ bool ret = JS_ReadUint32Pair(aReader, &length, &zero);
+ if (!ret) {
+ return false;
+ }
+
+ if (length > 0) {
+ if (!aBuffer.SetLength(length, fallible)) {
+ return false;
+ }
+ ret = JS_ReadBytes(aReader, aBuffer.Elements(), aBuffer.Length());
+ }
+ return ret;
+}
+
+inline bool
+WriteBuffer(JSStructuredCloneWriter* aWriter, const uint8_t* aBuffer, size_t aLength)
+{
+ bool ret = JS_WriteUint32Pair(aWriter, aLength, 0);
+ if (ret && aLength > 0) {
+ ret = JS_WriteBytes(aWriter, aBuffer, aLength);
+ }
+ return ret;
+}
+
+inline bool
+WriteBuffer(JSStructuredCloneWriter* aWriter, const CryptoBuffer& aBuffer)
+{
+ return WriteBuffer(aWriter, aBuffer.Elements(), aBuffer.Length());
+}
+
+inline CK_MECHANISM_TYPE
+MapAlgorithmNameToMechanism(const nsString& aName)
+{
+ CK_MECHANISM_TYPE mechanism(UNKNOWN_CK_MECHANISM);
+
+ // Set mechanism based on algorithm name
+ if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
+ mechanism = CKM_AES_CBC_PAD;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
+ mechanism = CKM_AES_CTR;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
+ mechanism = CKM_AES_GCM;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
+ mechanism = CKM_NSS_AES_KEY_WRAP;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
+ mechanism = CKM_SHA_1;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
+ mechanism = CKM_SHA256;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
+ mechanism = CKM_SHA384;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
+ mechanism = CKM_SHA512;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
+ mechanism = CKM_PKCS5_PBKD2;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+ mechanism = CKM_RSA_PKCS;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
+ mechanism = CKM_RSA_PKCS_OAEP;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
+ mechanism = CKM_RSA_PKCS_PSS;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
+ mechanism = CKM_ECDH1_DERIVE;
+ } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
+ mechanism = CKM_DH_PKCS_DERIVE;
+ }
+
+ return mechanism;
+}
+
+#define NORMALIZED_EQUALS(aTest, aConst) \
+ nsContentUtils::EqualsIgnoreASCIICase(aTest, NS_LITERAL_STRING(aConst))
+
+inline bool
+NormalizeToken(const nsString& aName, nsString& aDest)
+{
+ // Algorithm names
+ if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CBC)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CBC);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CTR)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CTR);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_GCM)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_GCM);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_KW)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_AES_KW);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA1)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA1);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA256)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA256);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA384)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA384);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA512)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_SHA512);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HMAC)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_HMAC);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HKDF)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_HKDF);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_PBKDF2)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSASSA_PKCS1)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_OAEP)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_PSS)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_PSS);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDH)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_ECDH);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDSA)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_ECDSA);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_DH)) {
+ aDest.AssignLiteral(WEBCRYPTO_ALG_DH);
+ // Named curve values
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
+ aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P384)) {
+ aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
+ } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P521)) {
+ aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+inline bool
+CheckEncodedECParameters(const SECItem* aEcParams)
+{
+ // Need at least two bytes for a valid ASN.1 encoding.
+ if (aEcParams->len < 2) {
+ return false;
+ }
+
+ // Check the ASN.1 tag.
+ if (aEcParams->data[0] != SEC_ASN1_OBJECT_ID) {
+ return false;
+ }
+
+ // OID tags are short, we never need more than one length byte.
+ if (aEcParams->data[1] >= 128) {
+ return false;
+ }
+
+ // Check that the SECItem's length is correct.
+ if (aEcParams->len != (unsigned)aEcParams->data[1] + 2) {
+ return false;
+ }
+
+ return true;
+}
+
+inline SECItem*
+CreateECParamsForCurve(const nsString& aNamedCurve, PLArenaPool* aArena)
+{
+ MOZ_ASSERT(aArena);
+ SECOidTag curveOIDTag;
+
+ if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
+ curveOIDTag = SEC_OID_SECG_EC_SECP256R1;
+ } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
+ curveOIDTag = SEC_OID_SECG_EC_SECP384R1;
+ } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
+ curveOIDTag = SEC_OID_SECG_EC_SECP521R1;
+ } else {
+ return nullptr;
+ }
+
+ // Retrieve curve data by OID tag.
+ SECOidData* oidData = SECOID_FindOIDByTag(curveOIDTag);
+ if (!oidData) {
+ return nullptr;
+ }
+
+ // Create parameters.
+ SECItem* params = ::SECITEM_AllocItem(aArena, nullptr, 2 + oidData->oid.len);
+ if (!params) {
+ return nullptr;
+ }
+
+ // Set parameters.
+ params->data[0] = SEC_ASN1_OBJECT_ID;
+ params->data[1] = oidData->oid.len;
+ memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
+
+ // Sanity check the params we just created.
+ if (!CheckEncodedECParameters(params)) {
+ return nullptr;
+ }
+
+ return params;
+}
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_WebCryptoCommon_h