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/. */
6 
7 #include "mozilla/dom/KeyAlgorithmProxy.h"
8 
9 #include "js/StructuredClone.h"
10 #include "mozilla/Assertions.h"
11 #include "mozilla/dom/StructuredCloneHolder.h"
12 #include "mozilla/dom/WebCryptoCommon.h"
13 
14 namespace mozilla::dom {
15 
WriteStructuredClone(JSStructuredCloneWriter * aWriter) const16 bool KeyAlgorithmProxy::WriteStructuredClone(
17     JSStructuredCloneWriter* aWriter) const {
18   if (!StructuredCloneHolder::WriteString(aWriter, mName) ||
19       !JS_WriteUint32Pair(aWriter, mType, KEY_ALGORITHM_SC_VERSION)) {
20     return false;
21   }
22 
23   switch (mType) {
24     case AES:
25       return JS_WriteUint32Pair(aWriter, mAes.mLength, 0);
26     case HMAC:
27       return JS_WriteUint32Pair(aWriter, mHmac.mLength, 0) &&
28              StructuredCloneHolder::WriteString(aWriter, mHmac.mHash.mName);
29     case RSA: {
30       return JS_WriteUint32Pair(aWriter, mRsa.mModulusLength, 0) &&
31              WriteBuffer(aWriter, mRsa.mPublicExponent) &&
32              StructuredCloneHolder::WriteString(aWriter, mRsa.mHash.mName);
33     }
34     case EC:
35       return StructuredCloneHolder::WriteString(aWriter, mEc.mNamedCurve);
36   }
37 
38   return false;
39 }
40 
ReadStructuredClone(JSStructuredCloneReader * aReader)41 bool KeyAlgorithmProxy::ReadStructuredClone(JSStructuredCloneReader* aReader) {
42   uint32_t type, version, dummy;
43   if (!StructuredCloneHolder::ReadString(aReader, mName) ||
44       !JS_ReadUint32Pair(aReader, &type, &version)) {
45     return false;
46   }
47 
48   if (version != KEY_ALGORITHM_SC_VERSION) {
49     return false;
50   }
51 
52   switch (type) {
53     case AES: {
54       mType = AES;
55 
56       uint32_t length;
57       if (!JS_ReadUint32Pair(aReader, &length, &dummy)) {
58         return false;
59       }
60 
61       mAes.mLength = length;
62       mAes.mName = mName;
63       return true;
64     }
65     case HMAC: {
66       mType = HMAC;
67 
68       if (!JS_ReadUint32Pair(aReader, &mHmac.mLength, &dummy) ||
69           !StructuredCloneHolder::ReadString(aReader, mHmac.mHash.mName)) {
70         return false;
71       }
72 
73       mHmac.mName = mName;
74       return true;
75     }
76     case RSA: {
77       mType = RSA;
78 
79       uint32_t modulusLength;
80       nsString hashName;
81       if (!JS_ReadUint32Pair(aReader, &modulusLength, &dummy) ||
82           !ReadBuffer(aReader, mRsa.mPublicExponent) ||
83           !StructuredCloneHolder::ReadString(aReader, mRsa.mHash.mName)) {
84         return false;
85       }
86 
87       mRsa.mModulusLength = modulusLength;
88       mRsa.mName = mName;
89       return true;
90     }
91     case EC: {
92       mType = EC;
93 
94       nsString namedCurve;
95       if (!StructuredCloneHolder::ReadString(aReader, mEc.mNamedCurve)) {
96         return false;
97       }
98 
99       mEc.mName = mName;
100       return true;
101     }
102   }
103 
104   return false;
105 }
106 
107 CK_MECHANISM_TYPE
Mechanism() const108 KeyAlgorithmProxy::Mechanism() const {
109   if (mType == HMAC) {
110     return GetMechanism(mHmac);
111   }
112   return MapAlgorithmNameToMechanism(mName);
113 }
114 
JwkAlg() const115 nsString KeyAlgorithmProxy::JwkAlg() const {
116   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
117     switch (mAes.mLength) {
118       case 128:
119         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128CBC);
120       case 192:
121         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192CBC);
122       case 256:
123         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256CBC);
124     }
125   }
126 
127   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
128     switch (mAes.mLength) {
129       case 128:
130         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128CTR);
131       case 192:
132         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192CTR);
133       case 256:
134         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256CTR);
135     }
136   }
137 
138   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
139     switch (mAes.mLength) {
140       case 128:
141         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128GCM);
142       case 192:
143         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192GCM);
144       case 256:
145         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256GCM);
146     }
147   }
148 
149   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
150     switch (mAes.mLength) {
151       case 128:
152         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128KW);
153       case 192:
154         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192KW);
155       case 256:
156         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256KW);
157     }
158   }
159 
160   if (mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
161     nsString hashName = mHmac.mHash.mName;
162     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
163       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS1);
164     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
165       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS256);
166     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
167       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS384);
168     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
169       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS512);
170     }
171   }
172 
173   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
174     nsString hashName = mRsa.mHash.mName;
175     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
176       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS1);
177     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
178       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS256);
179     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
180       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS384);
181     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
182       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS512);
183     }
184   }
185 
186   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
187     nsString hashName = mRsa.mHash.mName;
188     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
189       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP);
190     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
191       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_256);
192     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
193       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_384);
194     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
195       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_512);
196     }
197   }
198 
199   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
200     nsString hashName = mRsa.mHash.mName;
201     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
202       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS1);
203     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
204       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS256);
205     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
206       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS384);
207     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
208       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS512);
209     }
210   }
211 
212   if (mName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
213     nsString curveName = mEc.mNamedCurve;
214     if (curveName.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) {
215       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_ECDSA_P_256);
216     }
217     if (curveName.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) {
218       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_ECDSA_P_384);
219     }
220     if (curveName.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) {
221       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_ECDSA_P_521);
222     }
223   }
224 
225   return nsString();
226 }
227 
228 CK_MECHANISM_TYPE
GetMechanism(const KeyAlgorithm & aAlgorithm)229 KeyAlgorithmProxy::GetMechanism(const KeyAlgorithm& aAlgorithm) {
230   // For everything but HMAC, the name determines the mechanism
231   // HMAC is handled by the specialization below
232   return MapAlgorithmNameToMechanism(aAlgorithm.mName);
233 }
234 
235 CK_MECHANISM_TYPE
GetMechanism(const HmacKeyAlgorithm & aAlgorithm)236 KeyAlgorithmProxy::GetMechanism(const HmacKeyAlgorithm& aAlgorithm) {
237   // The use of HmacKeyAlgorithm doesn't completely prevent this
238   // method from being called with dictionaries that don't really
239   // represent HMAC key algorithms.
240   MOZ_ASSERT(aAlgorithm.mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC));
241 
242   CK_MECHANISM_TYPE hashMech;
243   hashMech = MapAlgorithmNameToMechanism(aAlgorithm.mHash.mName);
244 
245   switch (hashMech) {
246     case CKM_SHA_1:
247       return CKM_SHA_1_HMAC;
248     case CKM_SHA256:
249       return CKM_SHA256_HMAC;
250     case CKM_SHA384:
251       return CKM_SHA384_HMAC;
252     case CKM_SHA512:
253       return CKM_SHA512_HMAC;
254   }
255   return UNKNOWN_CK_MECHANISM;
256 }
257 
258 }  // namespace mozilla::dom
259