|
1 /* |
|
2 * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <x509keys.h> |
|
20 #include <asn1dec.h> |
|
21 #include <asn1enc.h> |
|
22 #include <x509cert.h> |
|
23 |
|
24 //DSA public key |
|
25 CX509DSAPublicKey::CX509DSAPublicKey() |
|
26 {} |
|
27 |
|
28 //dsa public key |
|
29 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewL(const TDesC8& aParamsData, const TDesC8& aBinaryData) |
|
30 { |
|
31 TInt pos = 0; |
|
32 return CX509DSAPublicKey::NewL(aParamsData, aBinaryData, pos); |
|
33 } |
|
34 |
|
35 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewLC(const TDesC8& aParamsData, const TDesC8& aBinaryData) |
|
36 { |
|
37 TInt pos = 0; |
|
38 return CX509DSAPublicKey::NewLC(aParamsData, aBinaryData, pos); |
|
39 } |
|
40 |
|
41 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewL(const TDesC8& aParamsData, const TDesC8& aBinaryData, TInt& aPos) |
|
42 { |
|
43 CX509DSAPublicKey* self = CX509DSAPublicKey::NewLC(aParamsData, aBinaryData, aPos); |
|
44 CleanupStack::Pop(); |
|
45 return self; |
|
46 } |
|
47 |
|
48 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewLC(const TDesC8& aParamsData, const TDesC8& aBinaryData, TInt& aPos) |
|
49 { |
|
50 CX509DSAPublicKey* self = new(ELeave) CX509DSAPublicKey; |
|
51 CleanupStack::PushL(self); |
|
52 self->ConstructL(aParamsData, aBinaryData, aPos); |
|
53 return self; |
|
54 } |
|
55 |
|
56 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewL(const CDSAParameters& aParams, const TDesC8& aBinaryData) |
|
57 { |
|
58 TInt pos = 0; |
|
59 CX509DSAPublicKey* self = CX509DSAPublicKey::NewLC(aParams, aBinaryData, pos); |
|
60 CleanupStack::Pop(); |
|
61 return self; |
|
62 } |
|
63 |
|
64 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewLC(const CDSAParameters& aParams, const TDesC8& aBinaryData) |
|
65 { |
|
66 TInt pos = 0; |
|
67 CX509DSAPublicKey* self = new(ELeave) CX509DSAPublicKey; |
|
68 CleanupStack::PushL(self); |
|
69 self->ConstructL(aParams, aBinaryData, pos); |
|
70 return self; |
|
71 } |
|
72 |
|
73 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewL(const CDSAParameters& aParams, const TDesC8& aBinaryData, TInt& aPos) |
|
74 { |
|
75 CX509DSAPublicKey* self = CX509DSAPublicKey::NewLC(aParams, aBinaryData, aPos); |
|
76 CleanupStack::Pop(); |
|
77 return self; |
|
78 } |
|
79 |
|
80 EXPORT_C CX509DSAPublicKey* CX509DSAPublicKey::NewLC(const CDSAParameters& aParams, const TDesC8& aBinaryData, TInt& aPos) |
|
81 { |
|
82 CX509DSAPublicKey* self = new(ELeave) CX509DSAPublicKey; |
|
83 CleanupStack::PushL(self); |
|
84 self->ConstructL(aParams, aBinaryData, aPos); |
|
85 return self; |
|
86 } |
|
87 |
|
88 void CX509DSAPublicKey::ConstructL(const TDesC8& aParamsData, const TDesC8& aBinaryData, TInt& aPos) |
|
89 { |
|
90 TASN1DecGeneric genParams(aParamsData.Right(aParamsData.Length() - aPos)); |
|
91 genParams.InitL(); |
|
92 TInt end = aPos + genParams.LengthDER(); |
|
93 aPos += genParams.LengthDERHeader(); |
|
94 if (genParams.Tag() != EASN1Sequence) |
|
95 { |
|
96 User::Leave(KErrArgument); |
|
97 } |
|
98 TASN1DecInteger encInt; |
|
99 iP = encInt.DecodeDERLongL(aParamsData, aPos); |
|
100 iQ = encInt.DecodeDERLongL(aParamsData, aPos); |
|
101 iG = encInt.DecodeDERLongL(aParamsData, aPos); |
|
102 if (aPos != end) |
|
103 { |
|
104 User::Leave(KErrArgument); |
|
105 } |
|
106 |
|
107 aPos = 0; |
|
108 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos)); |
|
109 gen.InitL(); |
|
110 end = aPos + gen.LengthDER(); |
|
111 iY = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
112 if (aPos != end) |
|
113 { |
|
114 User::Leave(KErrArgument); |
|
115 } |
|
116 } |
|
117 |
|
118 void CX509DSAPublicKey::ConstructL(const CDSAParameters& aParams, const TDesC8& aBinaryData, TInt& aPos) |
|
119 { |
|
120 iP = RInteger::NewL(aParams.P()); |
|
121 iQ = RInteger::NewL(aParams.Q()); |
|
122 iG = RInteger::NewL(aParams.G()); |
|
123 |
|
124 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos)); |
|
125 gen.InitL(); |
|
126 TInt end = aPos + gen.LengthDER(); |
|
127 TASN1DecInteger encInt; |
|
128 iY = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
129 if (aPos != end) |
|
130 { |
|
131 User::Leave(KErrArgument); |
|
132 } |
|
133 } |
|
134 |
|
135 |
|
136 EXPORT_C CDSAParameters* CX509DSAPublicKey::DSAParametersL(const TDesC8& aParamsData) |
|
137 { |
|
138 TInt pos = 0; |
|
139 TASN1DecGeneric genParams(aParamsData.Right(aParamsData.Length() - pos)); |
|
140 genParams.InitL(); |
|
141 TInt end = pos + genParams.LengthDER(); |
|
142 pos += genParams.LengthDERHeader(); |
|
143 if (genParams.Tag() != EASN1Sequence) |
|
144 { |
|
145 User::Leave(KErrArgument); |
|
146 } |
|
147 TASN1DecInteger encInt; |
|
148 RInteger P = encInt.DecodeDERLongL(aParamsData, pos); |
|
149 CleanupStack::PushL(P); |
|
150 RInteger Q = encInt.DecodeDERLongL(aParamsData, pos); |
|
151 CleanupStack::PushL(Q); |
|
152 RInteger G = encInt.DecodeDERLongL(aParamsData, pos); |
|
153 CleanupStack::PushL(G); |
|
154 if (pos != end) |
|
155 { |
|
156 User::Leave(KErrArgument); |
|
157 } |
|
158 |
|
159 CDSAParameters* theDSAParams = CDSAParameters::NewL(P, Q, G); |
|
160 CleanupStack::Pop(3, &P); |
|
161 return (theDSAParams); |
|
162 } |
|
163 |
|
164 // Decodes DSA keys from DER-encoded buffer |
|
165 EXPORT_C void TASN1DecDSAKeyPair::DecodeDERL(const TDesC8& aDER, TInt& aPos, |
|
166 CDSAPublicKey*& aPublicKey, |
|
167 CDSAPrivateKey*& aPrivateKey) |
|
168 { |
|
169 __UHEAP_MARK; |
|
170 aPublicKey = NULL; |
|
171 aPrivateKey = NULL; |
|
172 |
|
173 // Enter into the containing SEQUENCE and verify if it is |
|
174 // indeed there |
|
175 TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos)); |
|
176 gen.InitL(); |
|
177 TInt end = aPos + gen.LengthDER(); |
|
178 aPos += gen.LengthDERHeader(); |
|
179 if (gen.Tag() != EASN1Sequence) |
|
180 User::Leave(KErrArgument); |
|
181 |
|
182 TASN1DecInteger encInt; |
|
183 |
|
184 // Decode and discard version, which is an integer |
|
185 encInt.DecodeDERShortL(aDER, aPos); |
|
186 |
|
187 // Decode parameters |
|
188 // Decode p parameter |
|
189 RInteger p = encInt.DecodeDERLongL(aDER, aPos); |
|
190 CleanupStack::PushL(p); |
|
191 RInteger p1 = RInteger::NewL(p); |
|
192 CleanupStack::PushL(p1); |
|
193 |
|
194 // Decode q parameter |
|
195 RInteger q = encInt.DecodeDERLongL(aDER, aPos); |
|
196 CleanupStack::PushL(q); |
|
197 RInteger q1 = RInteger::NewL(q); |
|
198 CleanupStack::PushL(q1); |
|
199 |
|
200 // Decode g parameter |
|
201 RInteger g = encInt.DecodeDERLongL(aDER, aPos); |
|
202 CleanupStack::PushL(g); |
|
203 RInteger g1 = RInteger::NewL(g); |
|
204 CleanupStack::PushL(g1); |
|
205 |
|
206 // Decode private key x |
|
207 RInteger x = encInt.DecodeDERLongL(aDER, aPos); |
|
208 CleanupStack::PushL(x); |
|
209 // Decode public key y |
|
210 RInteger y = encInt.DecodeDERLongL(aDER, aPos); |
|
211 CleanupStack::PushL(y); |
|
212 |
|
213 // We now should be at the end of the encoding. If not, the |
|
214 // input encoding contains extra fields, and they are not |
|
215 // supported. |
|
216 if (aPos != end) |
|
217 User::Leave(KErrArgument); |
|
218 |
|
219 // Construct DSA public key |
|
220 CDSAPublicKey* dsaPublic = CDSAPublicKey::NewL(p, q, g, y); |
|
221 CleanupStack::PushL(dsaPublic); |
|
222 |
|
223 // Construct DSA key pair |
|
224 CDSAPrivateKey* dsaPrivate = CDSAPrivateKey::NewL(p1, q1, g1, x); |
|
225 CleanupStack::Pop(10, &p); // dsaPublic...p |
|
226 |
|
227 aPublicKey = dsaPublic; |
|
228 aPrivateKey = dsaPrivate; |
|
229 __UHEAP_MARKEND; |
|
230 } |
|
231 |
|
232 // Encodes DSA public key to DER |
|
233 EXPORT_C CASN1EncSequence* TASN1EncDSAPublicKey::EncodeDERL(const CDSAPublicKey& aKey) const |
|
234 { |
|
235 // Produce ASN.1 structure of DSA key parameters in the right order |
|
236 CASN1EncSequence* keySequence = CASN1EncSequence::NewLC(); |
|
237 CASN1EncSequence* encParams = EncodeParamsLC(aKey); |
|
238 keySequence->AddAndPopChildL(encParams); |
|
239 // encode public key as a bit string |
|
240 CASN1EncBitString* pubKeyBitString = EncodePublicValueLC(aKey); |
|
241 keySequence->AddAndPopChildL(pubKeyBitString); |
|
242 CleanupStack::Pop(keySequence); |
|
243 return keySequence; |
|
244 } |
|
245 |
|
246 // Encodes DSA parameters into ASN.1 sequence |
|
247 EXPORT_C CASN1EncSequence* TASN1EncDSAPublicKey::EncodeParamsLC(const CDSAPublicKey& aKey) const |
|
248 { |
|
249 CASN1EncSequence* sequence = CASN1EncSequence::NewLC(); |
|
250 CASN1EncBigInt* encParamP = CASN1EncBigInt::NewLC(aKey.P()); |
|
251 sequence->AddAndPopChildL(encParamP); |
|
252 CASN1EncBigInt* encParamQ = CASN1EncBigInt::NewLC(aKey.Q()); |
|
253 sequence->AddAndPopChildL(encParamQ); |
|
254 CASN1EncBigInt* encParamG = CASN1EncBigInt::NewLC(aKey.G()); |
|
255 sequence->AddAndPopChildL(encParamG); |
|
256 return sequence; |
|
257 } |
|
258 |
|
259 EXPORT_C CASN1EncBitString* TASN1EncDSAPublicKey::EncodePublicValueLC(const CDSAPublicKey& aKey) const |
|
260 { |
|
261 CASN1EncBigInt* bigint = CASN1EncBigInt::NewLC(aKey.Y()); |
|
262 CASN1EncBitString* pubKeyBitString = CASN1EncBitString::NewL(*bigint); |
|
263 CleanupStack::PopAndDestroy(bigint); |
|
264 CleanupStack::PushL(pubKeyBitString); |
|
265 return pubKeyBitString; |
|
266 } |
|
267 |
|
268 CX509DSASignature::CX509DSASignature() |
|
269 {} |
|
270 |
|
271 //DSA signature |
|
272 EXPORT_C CX509DSASignature* CX509DSASignature::NewL(const TDesC8& aBinaryData) |
|
273 { |
|
274 TInt pos = 0; |
|
275 return CX509DSASignature::NewL(aBinaryData, pos); |
|
276 } |
|
277 |
|
278 EXPORT_C CX509DSASignature* CX509DSASignature::NewLC(const TDesC8& aBinaryData) |
|
279 { |
|
280 TInt pos = 0; |
|
281 return CX509DSASignature::NewLC(aBinaryData, pos); |
|
282 } |
|
283 |
|
284 EXPORT_C CX509DSASignature* CX509DSASignature::NewL(const TDesC8& aBinaryData, TInt& aPos) |
|
285 { |
|
286 CX509DSASignature* self = CX509DSASignature::NewLC(aBinaryData, aPos); |
|
287 CleanupStack::Pop(); |
|
288 return self; |
|
289 } |
|
290 |
|
291 EXPORT_C CX509DSASignature* CX509DSASignature::NewLC(const TDesC8& aBinaryData, TInt& aPos) |
|
292 { |
|
293 CX509DSASignature* self = new(ELeave) CX509DSASignature; |
|
294 CleanupStack::PushL(self); |
|
295 self->ConstructL(aBinaryData, aPos); |
|
296 return self; |
|
297 } |
|
298 |
|
299 void CX509DSASignature::ConstructL(const TDesC8& aBinaryData, TInt& aPos) |
|
300 { |
|
301 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos)); |
|
302 gen.InitL(); |
|
303 TInt end = aPos + gen.LengthDER(); |
|
304 aPos += gen.LengthDERHeader(); |
|
305 if (gen.Tag() != EASN1Sequence) |
|
306 { |
|
307 User::Leave(KErrArgument); |
|
308 } |
|
309 TASN1DecInteger encInt; |
|
310 iR = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
311 iS = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
312 if (aPos != end) |
|
313 { |
|
314 User::Leave(KErrArgument); |
|
315 } |
|
316 } |
|
317 |
|
318 // |
|
319 // TX509DSAKeyEncoder Class Implementation |
|
320 // |
|
321 |
|
322 EXPORT_C TX509DSAKeyEncoder::TX509DSAKeyEncoder(const CDSAPublicKey& aKeyPublic, |
|
323 const TAlgorithmId aDigestAlg) |
|
324 : TX509KeyEncoder(aDigestAlg), |
|
325 iPublicKey(aKeyPublic) |
|
326 {} |
|
327 |
|
328 EXPORT_C CASN1EncBase* TX509DSAKeyEncoder::EncodeKeyLC() const |
|
329 { |
|
330 // Create higher-level sequence that will contain OID and the public key |
|
331 CASN1EncSequence* subjectPubKeyInfo = CASN1EncSequence::NewLC(); |
|
332 |
|
333 CASN1EncSequence* seq = CASN1EncSequence::NewLC(); |
|
334 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KDSA); |
|
335 seq->AddAndPopChildL(oid); |
|
336 |
|
337 // the next sequence will contain DSA parameters |
|
338 TASN1EncDSAPublicKey keyEnc; |
|
339 CASN1EncSequence* seqParams = keyEnc.EncodeParamsLC(iPublicKey); |
|
340 seq->AddAndPopChildL(seqParams); |
|
341 subjectPubKeyInfo->AddAndPopChildL(seq); |
|
342 |
|
343 // Add the key itself to the higher-level sequence as a bit string |
|
344 CASN1EncBigInt* pubPart = CASN1EncBigInt::NewLC(iPublicKey.Y()); |
|
345 HBufC8* encoding = HBufC8::NewMaxLC(pubPart->LengthDER()); |
|
346 TPtr8 encodingPtr = encoding->Des(); |
|
347 TUint pos = 0; |
|
348 pubPart->WriteDERL(encodingPtr, pos); |
|
349 CASN1EncBitString* pubkeyenc = CASN1EncBitString::NewLC(*encoding); |
|
350 subjectPubKeyInfo->AddAndPopChildL(pubkeyenc); |
|
351 CleanupStack::PopAndDestroy(2); // encoding, pubPart |
|
352 return subjectPubKeyInfo; |
|
353 } |
|
354 |
|
355 EXPORT_C CASN1EncSequence* TX509DSAKeyEncoder::EncodeSignatureAlgorithmLC() const |
|
356 { |
|
357 CASN1EncSequence* seq = CASN1EncSequence::NewLC(); |
|
358 CASN1EncObjectIdentifier* oid = NULL; |
|
359 |
|
360 // Determine OID string for the current combination of algorithms. |
|
361 switch(iDigestAlg) |
|
362 { |
|
363 default: |
|
364 User::Leave(KErrNotSupported); |
|
365 break; |
|
366 |
|
367 case ESHA1: |
|
368 oid = CASN1EncObjectIdentifier::NewLC(KDSAWithSHA1); |
|
369 break; |
|
370 } |
|
371 |
|
372 // Add algorithm OID to the sequence. |
|
373 seq->AddAndPopChildL(oid); |
|
374 // Insert p, q, and g big parameters into the sequence |
|
375 TASN1EncDSAPublicKey keyEnc; |
|
376 CASN1EncSequence* params = keyEnc.EncodeParamsLC(iPublicKey); |
|
377 seq->AddAndPopChildL(params); |
|
378 |
|
379 return seq; |
|
380 } |