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   mType = (KeyAlgorithmType)type;
53   switch (mType) {
54     case AES: {
55       uint32_t length;
56       if (!JS_ReadUint32Pair(aReader, &length, &dummy)) {
57         return false;
58       }
59 
60       mAes.mLength = length;
61       mAes.mName = mName;
62       return true;
63     }
64     case HMAC: {
65       if (!JS_ReadUint32Pair(aReader, &mHmac.mLength, &dummy) ||
66           !StructuredCloneHolder::ReadString(aReader, mHmac.mHash.mName)) {
67         return false;
68       }
69 
70       mHmac.mName = mName;
71       return true;
72     }
73     case RSA: {
74       uint32_t modulusLength;
75       nsString hashName;
76       if (!JS_ReadUint32Pair(aReader, &modulusLength, &dummy) ||
77           !ReadBuffer(aReader, mRsa.mPublicExponent) ||
78           !StructuredCloneHolder::ReadString(aReader, mRsa.mHash.mName)) {
79         return false;
80       }
81 
82       mRsa.mModulusLength = modulusLength;
83       mRsa.mName = mName;
84       return true;
85     }
86     case EC: {
87       nsString namedCurve;
88       if (!StructuredCloneHolder::ReadString(aReader, mEc.mNamedCurve)) {
89         return false;
90       }
91 
92       mEc.mName = mName;
93       return true;
94     }
95   }
96 
97   return false;
98 }
99 
100 CK_MECHANISM_TYPE
Mechanism() const101 KeyAlgorithmProxy::Mechanism() const {
102   if (mType == HMAC) {
103     return GetMechanism(mHmac);
104   }
105   return MapAlgorithmNameToMechanism(mName);
106 }
107 
JwkAlg() const108 nsString KeyAlgorithmProxy::JwkAlg() const {
109   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC)) {
110     switch (mAes.mLength) {
111       case 128:
112         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128CBC);
113       case 192:
114         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192CBC);
115       case 256:
116         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256CBC);
117     }
118   }
119 
120   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR)) {
121     switch (mAes.mLength) {
122       case 128:
123         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128CTR);
124       case 192:
125         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192CTR);
126       case 256:
127         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256CTR);
128     }
129   }
130 
131   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM)) {
132     switch (mAes.mLength) {
133       case 128:
134         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128GCM);
135       case 192:
136         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192GCM);
137       case 256:
138         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256GCM);
139     }
140   }
141 
142   if (mName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW)) {
143     switch (mAes.mLength) {
144       case 128:
145         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A128KW);
146       case 192:
147         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A192KW);
148       case 256:
149         return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_A256KW);
150     }
151   }
152 
153   if (mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
154     nsString hashName = mHmac.mHash.mName;
155     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
156       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS1);
157     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
158       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS256);
159     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
160       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS384);
161     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
162       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_HS512);
163     }
164   }
165 
166   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1)) {
167     nsString hashName = mRsa.mHash.mName;
168     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
169       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS1);
170     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
171       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS256);
172     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
173       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS384);
174     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
175       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RS512);
176     }
177   }
178 
179   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP)) {
180     nsString hashName = mRsa.mHash.mName;
181     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
182       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP);
183     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
184       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_256);
185     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
186       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_384);
187     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
188       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_RSA_OAEP_512);
189     }
190   }
191 
192   if (mName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
193     nsString hashName = mRsa.mHash.mName;
194     if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA1)) {
195       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS1);
196     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA256)) {
197       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS256);
198     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA384)) {
199       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS384);
200     } else if (hashName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
201       return NS_LITERAL_STRING_FROM_CSTRING(JWK_ALG_PS512);
202     }
203   }
204 
205   return nsString();
206 }
207 
208 CK_MECHANISM_TYPE
GetMechanism(const KeyAlgorithm & aAlgorithm)209 KeyAlgorithmProxy::GetMechanism(const KeyAlgorithm& aAlgorithm) {
210   // For everything but HMAC, the name determines the mechanism
211   // HMAC is handled by the specialization below
212   return MapAlgorithmNameToMechanism(aAlgorithm.mName);
213 }
214 
215 CK_MECHANISM_TYPE
GetMechanism(const HmacKeyAlgorithm & aAlgorithm)216 KeyAlgorithmProxy::GetMechanism(const HmacKeyAlgorithm& aAlgorithm) {
217   // The use of HmacKeyAlgorithm doesn't completely prevent this
218   // method from being called with dictionaries that don't really
219   // represent HMAC key algorithms.
220   MOZ_ASSERT(aAlgorithm.mName.EqualsLiteral(WEBCRYPTO_ALG_HMAC));
221 
222   CK_MECHANISM_TYPE hashMech;
223   hashMech = MapAlgorithmNameToMechanism(aAlgorithm.mHash.mName);
224 
225   switch (hashMech) {
226     case CKM_SHA_1:
227       return CKM_SHA_1_HMAC;
228     case CKM_SHA256:
229       return CKM_SHA256_HMAC;
230     case CKM_SHA384:
231       return CKM_SHA384_HMAC;
232     case CKM_SHA512:
233       return CKM_SHA512_HMAC;
234   }
235   return UNKNOWN_CK_MECHANISM;
236 }
237 
238 }  // namespace mozilla::dom
239