|
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 CX509RSAPublicKey::CX509RSAPublicKey() |
|
25 {} |
|
26 |
|
27 //RSA public key |
|
28 EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData) |
|
29 { |
|
30 TInt pos = 0; |
|
31 return CX509RSAPublicKey::NewL(aBinaryData, pos); |
|
32 } |
|
33 |
|
34 EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData) |
|
35 { |
|
36 TInt pos = 0; |
|
37 return CX509RSAPublicKey::NewLC(aBinaryData, pos); |
|
38 } |
|
39 |
|
40 EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewL(const TDesC8& aBinaryData, TInt& aPos) |
|
41 { |
|
42 CX509RSAPublicKey* self = CX509RSAPublicKey::NewLC(aBinaryData, aPos); |
|
43 CleanupStack::Pop(); |
|
44 return self; |
|
45 } |
|
46 |
|
47 EXPORT_C CX509RSAPublicKey* CX509RSAPublicKey::NewLC(const TDesC8& aBinaryData, TInt& aPos) |
|
48 { |
|
49 CX509RSAPublicKey* self = new(ELeave) CX509RSAPublicKey(); |
|
50 CleanupStack::PushL(self); |
|
51 self->ConstructL(aBinaryData, aPos); |
|
52 return self; |
|
53 } |
|
54 |
|
55 void CX509RSAPublicKey::ConstructL(const TDesC8& aBinaryData, TInt& aPos) |
|
56 { |
|
57 TASN1DecGeneric gen(aBinaryData.Right(aBinaryData.Length() - aPos)); |
|
58 gen.InitL(); |
|
59 TInt end = aPos + gen.LengthDER(); |
|
60 aPos += gen.LengthDERHeader(); |
|
61 if (gen.Tag() != EASN1Sequence) |
|
62 { |
|
63 User::Leave(KErrArgument); |
|
64 } |
|
65 TASN1DecInteger encInt; |
|
66 iN = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
67 iE = encInt.DecodeDERLongL(aBinaryData, aPos); |
|
68 |
|
69 // RSA Public keys, modulus and exponent must be positive integers |
|
70 if(!iN.IsPositive() || !iE.IsPositive()) |
|
71 { |
|
72 User::Leave(KErrArgument); |
|
73 } |
|
74 if (aPos != end) |
|
75 { |
|
76 User::Leave(KErrArgument); |
|
77 } |
|
78 } |
|
79 |
|
80 // Encodes public key to DER |
|
81 EXPORT_C HBufC8* TASN1EncRSAPublicKey::EncodeDERL(const CRSAPublicKey& aKey) const |
|
82 { |
|
83 CASN1EncSequence* sequence = CASN1EncSequence::NewLC(); |
|
84 CASN1EncBigInt* encModulus = CASN1EncBigInt::NewLC(aKey.N()); |
|
85 sequence->AddAndPopChildL(encModulus); |
|
86 CASN1EncBigInt* encPublicExponent = CASN1EncBigInt::NewLC(aKey.E()); |
|
87 sequence->AddAndPopChildL(encPublicExponent); |
|
88 HBufC8* der = HBufC8::NewMaxLC(sequence->LengthDER()); |
|
89 TUint pos = 0; |
|
90 TPtr8 derptr(der->Des()); |
|
91 sequence->WriteDERL(derptr, pos); |
|
92 CleanupStack::Pop(der); |
|
93 CleanupStack::PopAndDestroy(sequence); |
|
94 return der; |
|
95 } |
|
96 |
|
97 // Decodes public key from DER |
|
98 EXPORT_C CRSAPublicKey* TASN1DecRSAPublicKey::DecodeDERL(const TDesC8& aDER, |
|
99 TInt& aPos) const |
|
100 { |
|
101 // Enter into the containing SEQUENCE and verify if it is indeed there |
|
102 TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos)); |
|
103 gen.InitL(); |
|
104 TInt end = aPos + gen.LengthDER(); |
|
105 aPos += gen.LengthDERHeader(); |
|
106 if (gen.Tag() != EASN1Sequence) |
|
107 User::Leave(KErrArgument); |
|
108 |
|
109 // Decode modulus and public exponent (two large integers) |
|
110 TASN1DecInteger encInt; |
|
111 RInteger modulus = encInt.DecodeDERLongL(aDER, aPos); |
|
112 CleanupStack::PushL(modulus); |
|
113 RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos); |
|
114 CleanupStack::PushL(publicExponent); |
|
115 if (aPos != end) |
|
116 User::Leave(KErrArgument); |
|
117 |
|
118 // Construct a new key without copying |
|
119 CRSAPublicKey* key = CRSAPublicKey::NewL(modulus, publicExponent); |
|
120 CleanupStack::Pop(2); // modulus, publicExponent - owned by public key |
|
121 return key; |
|
122 } |
|
123 |
|
124 // Decodes RSA key pair from DER-encoded buffer |
|
125 EXPORT_C void TASN1DecRSAKeyPair::DecodeDERL(const TDesC8& aDER, |
|
126 TInt& aPos, |
|
127 CRSAPublicKey*& aPublicKey, |
|
128 CRSAPrivateKey*& aPrivateKey, |
|
129 TRSAPrivateKeyType aKeyType /*=EStandardCRT*/) |
|
130 { |
|
131 aPublicKey = NULL; |
|
132 aPrivateKey = NULL; |
|
133 |
|
134 // Enter into the containing SEQUENCE and verify if it is |
|
135 // indeed there |
|
136 TASN1DecGeneric gen(aDER.Right(aDER.Length() - aPos)); |
|
137 gen.InitL(); |
|
138 TInt end = aPos + gen.LengthDER(); |
|
139 aPos += gen.LengthDERHeader(); |
|
140 if (gen.Tag() != EASN1Sequence) |
|
141 User::Leave(KErrArgument); |
|
142 |
|
143 TASN1DecInteger encInt; |
|
144 |
|
145 // Decode and discard version, which is an integer |
|
146 encInt.DecodeDERShortL(aDER, aPos); |
|
147 |
|
148 // Decode public key components |
|
149 |
|
150 // Decode modulus |
|
151 RInteger publicModulus = encInt.DecodeDERLongL(aDER, aPos); |
|
152 CleanupStack::PushL(publicModulus); |
|
153 |
|
154 // Decode public exponent |
|
155 RInteger publicExponent = encInt.DecodeDERLongL(aDER, aPos); |
|
156 CleanupStack::PushL(publicExponent); |
|
157 |
|
158 // Construct public key |
|
159 CRSAPublicKey* publicKey = CRSAPublicKey::NewL(publicModulus, publicExponent); |
|
160 CleanupStack::Pop(2, &publicModulus); // Now owned by publicKey |
|
161 CleanupStack::PushL(publicKey); |
|
162 |
|
163 // Decode private key components |
|
164 |
|
165 // Copy modulus |
|
166 RInteger privateModulus = RInteger::NewL(publicKey->N()); |
|
167 CleanupStack::PushL(privateModulus); |
|
168 // Decode private exponent |
|
169 RInteger privateExponent = encInt.DecodeDERLongL(aDER, aPos); |
|
170 CleanupStack::PushL(privateExponent); |
|
171 // Decode prime 1 |
|
172 RInteger p = encInt.DecodeDERLongL(aDER, aPos); |
|
173 CleanupStack::PushL(p); |
|
174 // Decode prime 2 |
|
175 RInteger q = encInt.DecodeDERLongL(aDER, aPos); |
|
176 CleanupStack::PushL(q); |
|
177 // Decode exponent 1 |
|
178 RInteger dmp1 = encInt.DecodeDERLongL(aDER, aPos); |
|
179 CleanupStack::PushL(dmp1); |
|
180 // Decode exponent 2 |
|
181 RInteger dmq1 = encInt.DecodeDERLongL(aDER, aPos); |
|
182 CleanupStack::PushL(dmq1); |
|
183 // Decode coefficient |
|
184 RInteger the_iqmp = encInt.DecodeDERLongL(aDER, aPos); |
|
185 CleanupStack::PushL(the_iqmp); |
|
186 |
|
187 // We now should be at the end of the encoding. If not, the |
|
188 // input encoding contains extra fields, and they are not |
|
189 // supported. |
|
190 if (aPos != end) |
|
191 User::Leave(KErrArgument); |
|
192 |
|
193 // Construct private key |
|
194 CRSAPrivateKey* privateKey = NULL; |
|
195 if (EStandardCRT==aKeyType) |
|
196 { |
|
197 privateKey = CRSAPrivateKeyCRT::NewL(privateModulus, p, q, dmp1, dmq1, the_iqmp); |
|
198 } |
|
199 else if (EStandard==aKeyType) |
|
200 { |
|
201 privateKey = CRSAPrivateKeyStandard::NewL(privateModulus, privateExponent); |
|
202 } |
|
203 else |
|
204 User::Leave(KErrNotSupported); |
|
205 |
|
206 CleanupStack::Pop(8,publicKey); // publicKey, privateModulus, privateExponent, |
|
207 // p, q, dmp1, dmq1, iqmp |
|
208 |
|
209 // Cleanup the TIntegers not owned by private key objects |
|
210 if (EStandard==aKeyType) |
|
211 { |
|
212 p.Close(); |
|
213 q.Close(); |
|
214 dmp1.Close(); |
|
215 dmq1.Close(); |
|
216 the_iqmp.Close(); |
|
217 } |
|
218 else |
|
219 { |
|
220 privateExponent.Close(); |
|
221 } |
|
222 |
|
223 aPublicKey = publicKey; |
|
224 aPrivateKey = privateKey; |
|
225 } |
|
226 |
|
227 // TX509RSAKeyEncoder Class Implementation |
|
228 |
|
229 EXPORT_C TX509RSAKeyEncoder::TX509RSAKeyEncoder(const CRSAPublicKey& aPublicKey, TAlgorithmId aDigestAlg) |
|
230 : TX509KeyEncoder(aDigestAlg), |
|
231 iPublicKey(aPublicKey) |
|
232 { |
|
233 } |
|
234 |
|
235 EXPORT_C CASN1EncBase* TX509RSAKeyEncoder::EncodeKeyLC() const |
|
236 { |
|
237 // Create higher-level sequence that will contain OID and the public key |
|
238 CASN1EncSequence* subjectPubKeyInfo = CASN1EncSequence::NewLC(); |
|
239 |
|
240 // The next-level sequence will contain OID of the algorithm followed by NULL |
|
241 CASN1EncSequence* seq = CASN1EncSequence::NewLC(); |
|
242 CASN1EncObjectIdentifier* oid = CASN1EncObjectIdentifier::NewLC(KRSA); |
|
243 seq->AddAndPopChildL(oid); |
|
244 CASN1EncNull* null = CASN1EncNull::NewLC(); |
|
245 seq->AddAndPopChildL(null); |
|
246 subjectPubKeyInfo->AddAndPopChildL(seq); |
|
247 |
|
248 // Add the key itself to the higher-level sequence as a bit string |
|
249 // Obtain a copy of the entity's public key |
|
250 TASN1EncRSAPublicKey keyencoder; |
|
251 HBufC8* encoding = keyencoder.EncodeDERL(iPublicKey); |
|
252 CleanupStack::PushL(encoding); |
|
253 CASN1EncBitString* pubkeyenc = CASN1EncBitString::NewLC(*encoding); |
|
254 subjectPubKeyInfo->AddAndPopChildL(pubkeyenc); |
|
255 CleanupStack::PopAndDestroy(encoding); |
|
256 return subjectPubKeyInfo; |
|
257 } |
|
258 |
|
259 // Returns ASN.1 sequence containing encoded signature algorithm. |
|
260 EXPORT_C CASN1EncSequence* TX509RSAKeyEncoder::EncodeSignatureAlgorithmLC() const |
|
261 { |
|
262 CASN1EncSequence* seq = CASN1EncSequence::NewLC(); |
|
263 CASN1EncObjectIdentifier* oid = NULL; |
|
264 |
|
265 // Determine OID string for the current combination of algorithms. |
|
266 switch(iDigestAlg) |
|
267 { |
|
268 default: |
|
269 User::Leave(KErrNotSupported); |
|
270 break; |
|
271 |
|
272 case EMD2: |
|
273 oid = CASN1EncObjectIdentifier::NewLC(KMD2WithRSA); |
|
274 break; |
|
275 |
|
276 case EMD5: |
|
277 oid = CASN1EncObjectIdentifier::NewLC(KMD5WithRSA); |
|
278 break; |
|
279 |
|
280 case ESHA1: |
|
281 oid = CASN1EncObjectIdentifier::NewLC(KSHA1WithRSA); |
|
282 break; |
|
283 } |
|
284 |
|
285 // Add algorithm OID to the sequence. |
|
286 seq->AddAndPopChildL(oid); |
|
287 // Add NULL after OID. |
|
288 CASN1EncNull* null = CASN1EncNull::NewLC(); |
|
289 seq->AddAndPopChildL(null); |
|
290 |
|
291 return seq; |
|
292 } |