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