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