Bug 1660051 [wpt PR 25111] - Origin isolation: expand getter test coverage, a=testonly
[gecko.git] / dom / crypto / WebCryptoCommon.h
blob95200da1ca9fefff71ac22ca26e77adeb7ca7383
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_WebCryptoCommon_h
8 #define mozilla_dom_WebCryptoCommon_h
10 #include "js/StructuredClone.h"
11 #include "mozilla/ArrayUtils.h"
12 #include "mozilla/dom/CryptoBuffer.h"
13 #include "nsContentUtils.h"
14 #include "nsString.h"
15 #include "pk11pub.h"
17 // WebCrypto algorithm names
18 #define WEBCRYPTO_ALG_AES_CBC "AES-CBC"
19 #define WEBCRYPTO_ALG_AES_CTR "AES-CTR"
20 #define WEBCRYPTO_ALG_AES_GCM "AES-GCM"
21 #define WEBCRYPTO_ALG_AES_KW "AES-KW"
22 #define WEBCRYPTO_ALG_SHA1 "SHA-1"
23 #define WEBCRYPTO_ALG_SHA256 "SHA-256"
24 #define WEBCRYPTO_ALG_SHA384 "SHA-384"
25 #define WEBCRYPTO_ALG_SHA512 "SHA-512"
26 #define WEBCRYPTO_ALG_HMAC "HMAC"
27 #define WEBCRYPTO_ALG_HKDF "HKDF"
28 #define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
29 #define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
30 #define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
31 #define WEBCRYPTO_ALG_RSA_PSS "RSA-PSS"
32 #define WEBCRYPTO_ALG_ECDH "ECDH"
33 #define WEBCRYPTO_ALG_ECDSA "ECDSA"
35 // WebCrypto key formats
36 #define WEBCRYPTO_KEY_FORMAT_RAW "raw"
37 #define WEBCRYPTO_KEY_FORMAT_PKCS8 "pkcs8"
38 #define WEBCRYPTO_KEY_FORMAT_SPKI "spki"
39 #define WEBCRYPTO_KEY_FORMAT_JWK "jwk"
41 // WebCrypto key types
42 #define WEBCRYPTO_KEY_TYPE_PUBLIC "public"
43 #define WEBCRYPTO_KEY_TYPE_PRIVATE "private"
44 #define WEBCRYPTO_KEY_TYPE_SECRET "secret"
46 // WebCrypto key usages
47 #define WEBCRYPTO_KEY_USAGE_ENCRYPT "encrypt"
48 #define WEBCRYPTO_KEY_USAGE_DECRYPT "decrypt"
49 #define WEBCRYPTO_KEY_USAGE_SIGN "sign"
50 #define WEBCRYPTO_KEY_USAGE_VERIFY "verify"
51 #define WEBCRYPTO_KEY_USAGE_DERIVEKEY "deriveKey"
52 #define WEBCRYPTO_KEY_USAGE_DERIVEBITS "deriveBits"
53 #define WEBCRYPTO_KEY_USAGE_WRAPKEY "wrapKey"
54 #define WEBCRYPTO_KEY_USAGE_UNWRAPKEY "unwrapKey"
56 // WebCrypto named curves
57 #define WEBCRYPTO_NAMED_CURVE_P256 "P-256"
58 #define WEBCRYPTO_NAMED_CURVE_P384 "P-384"
59 #define WEBCRYPTO_NAMED_CURVE_P521 "P-521"
61 // JWK key types
62 #define JWK_TYPE_SYMMETRIC "oct"
63 #define JWK_TYPE_RSA "RSA"
64 #define JWK_TYPE_EC "EC"
66 // JWK algorithms
67 #define JWK_ALG_A128CBC "A128CBC" // CBC
68 #define JWK_ALG_A192CBC "A192CBC"
69 #define JWK_ALG_A256CBC "A256CBC"
70 #define JWK_ALG_A128CTR "A128CTR" // CTR
71 #define JWK_ALG_A192CTR "A192CTR"
72 #define JWK_ALG_A256CTR "A256CTR"
73 #define JWK_ALG_A128GCM "A128GCM" // GCM
74 #define JWK_ALG_A192GCM "A192GCM"
75 #define JWK_ALG_A256GCM "A256GCM"
76 #define JWK_ALG_A128KW "A128KW" // KW
77 #define JWK_ALG_A192KW "A192KW"
78 #define JWK_ALG_A256KW "A256KW"
79 #define JWK_ALG_HS1 "HS1" // HMAC
80 #define JWK_ALG_HS256 "HS256"
81 #define JWK_ALG_HS384 "HS384"
82 #define JWK_ALG_HS512 "HS512"
83 #define JWK_ALG_RS1 "RS1" // RSASSA-PKCS1
84 #define JWK_ALG_RS256 "RS256"
85 #define JWK_ALG_RS384 "RS384"
86 #define JWK_ALG_RS512 "RS512"
87 #define JWK_ALG_RSA_OAEP "RSA-OAEP" // RSA-OAEP
88 #define JWK_ALG_RSA_OAEP_256 "RSA-OAEP-256"
89 #define JWK_ALG_RSA_OAEP_384 "RSA-OAEP-384"
90 #define JWK_ALG_RSA_OAEP_512 "RSA-OAEP-512"
91 #define JWK_ALG_PS1 "PS1" // RSA-PSS
92 #define JWK_ALG_PS256 "PS256"
93 #define JWK_ALG_PS384 "PS384"
94 #define JWK_ALG_PS512 "PS512"
95 #define JWK_ALG_ECDSA_P_256 "ES256"
96 #define JWK_ALG_ECDSA_P_384 "ES384"
97 #define JWK_ALG_ECDSA_P_521 "ES521"
99 // JWK usages
100 #define JWK_USE_ENC "enc"
101 #define JWK_USE_SIG "sig"
103 // Define an unknown mechanism type
104 #define UNKNOWN_CK_MECHANISM CKM_VENDOR_DEFINED + 1
106 // python security/pkix/tools/DottedOIDToCode.py id-ecDH 1.3.132.112
107 static const uint8_t id_ecDH[] = {0x2b, 0x81, 0x04, 0x70};
108 const SECItem SEC_OID_DATA_EC_DH = {
109 siBuffer, (unsigned char*)id_ecDH,
110 static_cast<unsigned int>(mozilla::ArrayLength(id_ecDH))};
112 namespace mozilla {
113 namespace dom {
115 inline bool ReadBuffer(JSStructuredCloneReader* aReader,
116 CryptoBuffer& aBuffer) {
117 uint32_t length, zero;
118 bool ret = JS_ReadUint32Pair(aReader, &length, &zero);
119 if (!ret) {
120 return false;
123 if (length > 0) {
124 if (!aBuffer.SetLength(length, fallible)) {
125 return false;
127 ret = JS_ReadBytes(aReader, aBuffer.Elements(), aBuffer.Length());
129 return ret;
132 inline bool WriteBuffer(JSStructuredCloneWriter* aWriter,
133 const uint8_t* aBuffer, size_t aLength) {
134 bool ret = JS_WriteUint32Pair(aWriter, aLength, 0);
135 if (ret && aLength > 0) {
136 ret = JS_WriteBytes(aWriter, aBuffer, aLength);
138 return ret;
141 inline bool WriteBuffer(JSStructuredCloneWriter* aWriter,
142 const CryptoBuffer& aBuffer) {
143 return WriteBuffer(aWriter, aBuffer.Elements(), aBuffer.Length());
146 inline CK_MECHANISM_TYPE MapAlgorithmNameToMechanism(const nsString& aName) {
147 CK_MECHANISM_TYPE mechanism(UNKNOWN_CK_MECHANISM);
149 // Set mechanism based on algorithm name
150 if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
151 mechanism = CKM_AES_CBC_PAD;
152 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
153 mechanism = CKM_AES_CTR;
154 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
155 mechanism = CKM_AES_GCM;
156 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
157 mechanism = CKM_NSS_AES_KEY_WRAP;
158 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
159 mechanism = CKM_SHA_1;
160 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
161 mechanism = CKM_SHA256;
162 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
163 mechanism = CKM_SHA384;
164 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
165 mechanism = CKM_SHA512;
166 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
167 mechanism = CKM_PKCS5_PBKD2;
168 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
169 mechanism = CKM_RSA_PKCS;
170 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
171 mechanism = CKM_RSA_PKCS_OAEP;
172 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
173 mechanism = CKM_RSA_PKCS_PSS;
174 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
175 mechanism = CKM_ECDH1_DERIVE;
178 return mechanism;
181 #define NORMALIZED_EQUALS(aTest, aConst) \
182 nsContentUtils::EqualsIgnoreASCIICase( \
183 aTest, NS_LITERAL_STRING_FROM_CSTRING(aConst))
185 inline bool NormalizeToken(const nsString& aName, nsString& aDest) {
186 // Algorithm names
187 if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CBC)) {
188 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CBC);
189 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CTR)) {
190 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CTR);
191 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_GCM)) {
192 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_GCM);
193 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_KW)) {
194 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_KW);
195 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA1)) {
196 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA1);
197 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA256)) {
198 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA256);
199 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA384)) {
200 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA384);
201 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA512)) {
202 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA512);
203 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HMAC)) {
204 aDest.AssignLiteral(WEBCRYPTO_ALG_HMAC);
205 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HKDF)) {
206 aDest.AssignLiteral(WEBCRYPTO_ALG_HKDF);
207 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_PBKDF2)) {
208 aDest.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
209 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSASSA_PKCS1)) {
210 aDest.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
211 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_OAEP)) {
212 aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
213 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_PSS)) {
214 aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_PSS);
215 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDH)) {
216 aDest.AssignLiteral(WEBCRYPTO_ALG_ECDH);
217 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDSA)) {
218 aDest.AssignLiteral(WEBCRYPTO_ALG_ECDSA);
219 // Named curve values
220 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
221 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
222 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P384)) {
223 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
224 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P521)) {
225 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
226 } else {
227 return false;
230 return true;
233 inline bool CheckEncodedECParameters(const SECItem* aEcParams) {
234 // Need at least two bytes for a valid ASN.1 encoding.
235 if (aEcParams->len < 2) {
236 return false;
239 // Check the ASN.1 tag.
240 if (aEcParams->data[0] != SEC_ASN1_OBJECT_ID) {
241 return false;
244 // OID tags are short, we never need more than one length byte.
245 if (aEcParams->data[1] >= 128) {
246 return false;
249 // Check that the SECItem's length is correct.
250 if (aEcParams->len != (unsigned)aEcParams->data[1] + 2) {
251 return false;
254 return true;
257 inline SECItem* CreateECParamsForCurve(const nsString& aNamedCurve,
258 PLArenaPool* aArena) {
259 MOZ_ASSERT(aArena);
260 SECOidTag curveOIDTag;
262 if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
263 curveOIDTag = SEC_OID_SECG_EC_SECP256R1;
264 } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
265 curveOIDTag = SEC_OID_SECG_EC_SECP384R1;
266 } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
267 curveOIDTag = SEC_OID_SECG_EC_SECP521R1;
268 } else {
269 return nullptr;
272 // Retrieve curve data by OID tag.
273 SECOidData* oidData = SECOID_FindOIDByTag(curveOIDTag);
274 if (!oidData) {
275 return nullptr;
278 // Create parameters.
279 SECItem* params = ::SECITEM_AllocItem(aArena, nullptr, 2 + oidData->oid.len);
280 if (!params) {
281 return nullptr;
284 // Set parameters.
285 params->data[0] = SEC_ASN1_OBJECT_ID;
286 params->data[1] = oidData->oid.len;
287 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
289 // Sanity check the params we just created.
290 if (!CheckEncodedECParameters(params)) {
291 return nullptr;
294 return params;
297 } // namespace dom
298 } // namespace mozilla
300 #endif // mozilla_dom_WebCryptoCommon_h