Bumping gaia.json for 4 gaia revision(s) a=gaia-bump
[gecko.git] / dom / crypto / WebCryptoCommon.h
blob33444a1f8f861abfaac3efd0c3f1ae66c980647f
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 "pk11pub.h"
11 #include "nsString.h"
12 #include "nsContentUtils.h"
13 #include "mozilla/dom/CryptoBuffer.h"
14 #include "js/StructuredClone.h"
16 // WebCrypto algorithm names
17 #define WEBCRYPTO_ALG_AES_CBC "AES-CBC"
18 #define WEBCRYPTO_ALG_AES_CTR "AES-CTR"
19 #define WEBCRYPTO_ALG_AES_GCM "AES-GCM"
20 #define WEBCRYPTO_ALG_AES_KW "AES-KW"
21 #define WEBCRYPTO_ALG_SHA1 "SHA-1"
22 #define WEBCRYPTO_ALG_SHA256 "SHA-256"
23 #define WEBCRYPTO_ALG_SHA384 "SHA-384"
24 #define WEBCRYPTO_ALG_SHA512 "SHA-512"
25 #define WEBCRYPTO_ALG_HMAC "HMAC"
26 #define WEBCRYPTO_ALG_PBKDF2 "PBKDF2"
27 #define WEBCRYPTO_ALG_RSASSA_PKCS1 "RSASSA-PKCS1-v1_5"
28 #define WEBCRYPTO_ALG_RSA_OAEP "RSA-OAEP"
29 #define WEBCRYPTO_ALG_ECDH "ECDH"
30 #define WEBCRYPTO_ALG_ECDSA "ECDSA"
31 #define WEBCRYPTO_ALG_DH "DH"
33 // WebCrypto key formats
34 #define WEBCRYPTO_KEY_FORMAT_RAW "raw"
35 #define WEBCRYPTO_KEY_FORMAT_PKCS8 "pkcs8"
36 #define WEBCRYPTO_KEY_FORMAT_SPKI "spki"
37 #define WEBCRYPTO_KEY_FORMAT_JWK "jwk"
39 // WebCrypto key types
40 #define WEBCRYPTO_KEY_TYPE_PUBLIC "public"
41 #define WEBCRYPTO_KEY_TYPE_PRIVATE "private"
42 #define WEBCRYPTO_KEY_TYPE_SECRET "secret"
44 // WebCrypto key usages
45 #define WEBCRYPTO_KEY_USAGE_ENCRYPT "encrypt"
46 #define WEBCRYPTO_KEY_USAGE_DECRYPT "decrypt"
47 #define WEBCRYPTO_KEY_USAGE_SIGN "sign"
48 #define WEBCRYPTO_KEY_USAGE_VERIFY "verify"
49 #define WEBCRYPTO_KEY_USAGE_DERIVEKEY "deriveKey"
50 #define WEBCRYPTO_KEY_USAGE_DERIVEBITS "deriveBits"
51 #define WEBCRYPTO_KEY_USAGE_WRAPKEY "wrapKey"
52 #define WEBCRYPTO_KEY_USAGE_UNWRAPKEY "unwrapKey"
54 // WebCrypto named curves
55 #define WEBCRYPTO_NAMED_CURVE_P256 "P-256"
56 #define WEBCRYPTO_NAMED_CURVE_P384 "P-384"
57 #define WEBCRYPTO_NAMED_CURVE_P521 "P-521"
59 // JWK key types
60 #define JWK_TYPE_SYMMETRIC "oct"
61 #define JWK_TYPE_RSA "RSA"
62 #define JWK_TYPE_EC "EC"
64 // JWK algorithms
65 #define JWK_ALG_A128CBC "A128CBC" // CBC
66 #define JWK_ALG_A192CBC "A192CBC"
67 #define JWK_ALG_A256CBC "A256CBC"
68 #define JWK_ALG_A128CTR "A128CTR" // CTR
69 #define JWK_ALG_A192CTR "A192CTR"
70 #define JWK_ALG_A256CTR "A256CTR"
71 #define JWK_ALG_A128GCM "A128GCM" // GCM
72 #define JWK_ALG_A192GCM "A192GCM"
73 #define JWK_ALG_A256GCM "A256GCM"
74 #define JWK_ALG_A128KW "A128KW" // KW
75 #define JWK_ALG_A192KW "A192KW"
76 #define JWK_ALG_A256KW "A256KW"
77 #define JWK_ALG_HS1 "HS1" // HMAC
78 #define JWK_ALG_HS256 "HS256"
79 #define JWK_ALG_HS384 "HS384"
80 #define JWK_ALG_HS512 "HS512"
81 #define JWK_ALG_RS1 "RS1" // RSASSA-PKCS1
82 #define JWK_ALG_RS256 "RS256"
83 #define JWK_ALG_RS384 "RS384"
84 #define JWK_ALG_RS512 "RS512"
85 #define JWK_ALG_RSA_OAEP "RSA-OAEP" // RSA-OAEP
86 #define JWK_ALG_RSA_OAEP_256 "RSA-OAEP-256"
87 #define JWK_ALG_RSA_OAEP_384 "RSA-OAEP-384"
88 #define JWK_ALG_RSA_OAEP_512 "RSA-OAEP-512"
89 #define JWK_ALG_ECDSA_P_256 "ES256"
90 #define JWK_ALG_ECDSA_P_384 "ES384"
91 #define JWK_ALG_ECDSA_P_521 "ES521"
93 // JWK usages
94 #define JWK_USE_ENC "enc"
95 #define JWK_USE_SIG "sig"
97 // Define an unknown mechanism type
98 #define UNKNOWN_CK_MECHANISM CKM_VENDOR_DEFINED+1
100 // python security/pkix/tools/DottedOIDToCode.py id-ecDH 1.3.132.112
101 static const uint8_t id_ecDH[] = { 0x2b, 0x81, 0x04, 0x70 };
102 const SECItem SEC_OID_DATA_EC_DH = { siBuffer, (unsigned char*)id_ecDH,
103 PR_ARRAY_SIZE(id_ecDH) };
105 // python security/pkix/tools/DottedOIDToCode.py dhKeyAgreement 1.2.840.113549.1.3.1
106 static const uint8_t dhKeyAgreement[] = {
107 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03, 0x01
109 const SECItem SEC_OID_DATA_DH_KEY_AGREEMENT = { siBuffer,
110 (unsigned char*)dhKeyAgreement,
111 PR_ARRAY_SIZE(dhKeyAgreement) };
113 namespace mozilla {
114 namespace dom {
116 // Helper functions for structured cloning
117 inline bool
118 ReadString(JSStructuredCloneReader* aReader, nsString& aString)
120 bool read;
121 uint32_t nameLength, zero;
122 read = JS_ReadUint32Pair(aReader, &nameLength, &zero);
123 if (!read) {
124 return false;
127 aString.SetLength(nameLength);
128 size_t charSize = sizeof(nsString::char_type);
129 read = JS_ReadBytes(aReader, (void*) aString.BeginWriting(), nameLength * charSize);
130 if (!read) {
131 return false;
134 return true;
137 inline bool
138 WriteString(JSStructuredCloneWriter* aWriter, const nsString& aString)
140 size_t charSize = sizeof(nsString::char_type);
141 return JS_WriteUint32Pair(aWriter, aString.Length(), 0) &&
142 JS_WriteBytes(aWriter, aString.get(), aString.Length() * charSize);
145 inline bool
146 ReadBuffer(JSStructuredCloneReader* aReader, CryptoBuffer& aBuffer)
148 uint32_t length, zero;
149 bool ret = JS_ReadUint32Pair(aReader, &length, &zero);
150 if (!ret) {
151 return false;
154 if (length > 0) {
155 if (!aBuffer.SetLength(length)) {
156 return false;
158 ret = JS_ReadBytes(aReader, aBuffer.Elements(), aBuffer.Length());
160 return ret;
163 inline bool
164 WriteBuffer(JSStructuredCloneWriter* aWriter, const CryptoBuffer& aBuffer)
166 bool ret = JS_WriteUint32Pair(aWriter, aBuffer.Length(), 0);
167 if (ret && aBuffer.Length() > 0) {
168 ret = JS_WriteBytes(aWriter, aBuffer.Elements(), aBuffer.Length());
170 return ret;
173 inline CK_MECHANISM_TYPE
174 MapAlgorithmNameToMechanism(const nsString& aName)
176 CK_MECHANISM_TYPE mechanism(UNKNOWN_CK_MECHANISM);
178 // Set mechanism based on algorithm name
179 if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
180 mechanism = CKM_AES_CBC_PAD;
181 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
182 mechanism = CKM_AES_CTR;
183 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
184 mechanism = CKM_AES_GCM;
185 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
186 mechanism = CKM_NSS_AES_KEY_WRAP;
187 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
188 mechanism = CKM_SHA_1;
189 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
190 mechanism = CKM_SHA256;
191 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
192 mechanism = CKM_SHA384;
193 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
194 mechanism = CKM_SHA512;
195 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2)) {
196 mechanism = CKM_PKCS5_PBKD2;
197 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
198 mechanism = CKM_RSA_PKCS;
199 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
200 mechanism = CKM_RSA_PKCS_OAEP;
201 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_ECDH)) {
202 mechanism = CKM_ECDH1_DERIVE;
203 } else if (aName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
204 mechanism = CKM_DH_PKCS_DERIVE;
207 return mechanism;
210 #define NORMALIZED_EQUALS(aTest, aConst) \
211 nsContentUtils::EqualsIgnoreASCIICase(aTest, NS_LITERAL_STRING(aConst))
213 inline bool
214 NormalizeToken(const nsString& aName, nsString& aDest)
216 // Algorithm names
217 if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CBC)) {
218 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CBC);
219 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_CTR)) {
220 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_CTR);
221 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_GCM)) {
222 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_GCM);
223 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_AES_KW)) {
224 aDest.AssignLiteral(WEBCRYPTO_ALG_AES_KW);
225 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA1)) {
226 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA1);
227 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA256)) {
228 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA256);
229 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA384)) {
230 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA384);
231 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_SHA512)) {
232 aDest.AssignLiteral(WEBCRYPTO_ALG_SHA512);
233 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_HMAC)) {
234 aDest.AssignLiteral(WEBCRYPTO_ALG_HMAC);
235 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_PBKDF2)) {
236 aDest.AssignLiteral(WEBCRYPTO_ALG_PBKDF2);
237 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSASSA_PKCS1)) {
238 aDest.AssignLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1);
239 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_RSA_OAEP)) {
240 aDest.AssignLiteral(WEBCRYPTO_ALG_RSA_OAEP);
241 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDH)) {
242 aDest.AssignLiteral(WEBCRYPTO_ALG_ECDH);
243 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_ECDSA)) {
244 aDest.AssignLiteral(WEBCRYPTO_ALG_ECDSA);
245 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_ALG_DH)) {
246 aDest.AssignLiteral(WEBCRYPTO_ALG_DH);
247 // Named curve values
248 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P256)) {
249 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P256);
250 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P384)) {
251 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P384);
252 } else if (NORMALIZED_EQUALS(aName, WEBCRYPTO_NAMED_CURVE_P521)) {
253 aDest.AssignLiteral(WEBCRYPTO_NAMED_CURVE_P521);
254 } else {
255 return false;
258 return true;
261 inline bool
262 CheckEncodedECParameters(const SECItem* aEcParams)
264 // Need at least two bytes for a valid ASN.1 encoding.
265 if (aEcParams->len < 2) {
266 return false;
269 // Check the ASN.1 tag.
270 if (aEcParams->data[0] != SEC_ASN1_OBJECT_ID) {
271 return false;
274 // OID tags are short, we never need more than one length byte.
275 if (aEcParams->data[1] >= 128) {
276 return false;
279 // Check that the SECItem's length is correct.
280 if (aEcParams->len != (unsigned)aEcParams->data[1] + 2) {
281 return false;
284 return true;
287 inline SECItem*
288 CreateECParamsForCurve(const nsString& aNamedCurve, PLArenaPool* aArena)
290 SECOidTag curveOIDTag;
292 if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
293 curveOIDTag = SEC_OID_SECG_EC_SECP256R1;
294 } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
295 curveOIDTag = SEC_OID_SECG_EC_SECP384R1;
296 } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
297 curveOIDTag = SEC_OID_SECG_EC_SECP521R1;
298 } else {
299 return nullptr;
302 // Retrieve curve data by OID tag.
303 SECOidData* oidData = SECOID_FindOIDByTag(curveOIDTag);
304 if (!oidData) {
305 return nullptr;
308 // Create parameters.
309 SECItem* params = ::SECITEM_AllocItem(aArena, nullptr, 2 + oidData->oid.len);
310 if (!params) {
311 return nullptr;
314 // Set parameters.
315 params->data[0] = SEC_ASN1_OBJECT_ID;
316 params->data[1] = oidData->oid.len;
317 memcpy(params->data + 2, oidData->oid.data, oidData->oid.len);
319 // Sanity check the params we just created.
320 if (!CheckEncodedECParameters(params)) {
321 return nullptr;
324 return params;
327 } // namespace dom
328 } // namespace mozilla
330 #endif // mozilla_dom_WebCryptoCommon_h