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