|
1 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
4 |
|
5 #include "cmmf.h" |
|
6 #include "cmmfi.h" |
|
7 |
|
8 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate) |
|
9 SEC_ASN1_MKSUB(SEC_AnyTemplate) |
|
10 SEC_ASN1_MKSUB(SEC_IntegerTemplate) |
|
11 SEC_ASN1_MKSUB(SEC_SignedCertificateTemplate) |
|
12 |
|
13 static const SEC_ASN1Template CMMFCertResponseTemplate[] = { |
|
14 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertResponse)}, |
|
15 { SEC_ASN1_INTEGER, offsetof(CMMFCertResponse, certReqId)}, |
|
16 { SEC_ASN1_INLINE, offsetof(CMMFCertResponse, status), |
|
17 CMMFPKIStatusInfoTemplate}, |
|
18 { SEC_ASN1_OPTIONAL | SEC_ASN1_POINTER, |
|
19 offsetof(CMMFCertResponse, certifiedKeyPair), |
|
20 CMMFCertifiedKeyPairTemplate}, |
|
21 { 0 } |
|
22 }; |
|
23 |
|
24 static const SEC_ASN1Template CMMFCertOrEncCertTemplate[] = { |
|
25 { SEC_ASN1_ANY, offsetof(CMMFCertOrEncCert, derValue), NULL, |
|
26 sizeof(CMMFCertOrEncCert)}, |
|
27 { 0 } |
|
28 }; |
|
29 |
|
30 const SEC_ASN1Template CMMFCertifiedKeyPairTemplate[] = { |
|
31 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertifiedKeyPair)}, |
|
32 { SEC_ASN1_INLINE, offsetof(CMMFCertifiedKeyPair, certOrEncCert), |
|
33 CMMFCertOrEncCertTemplate }, |
|
34 { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_POINTER | 0, |
|
35 offsetof(CMMFCertifiedKeyPair, privateKey), |
|
36 CRMFEncryptedValueTemplate}, |
|
37 { SEC_ASN1_NO_STREAM | SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | |
|
38 SEC_ASN1_XTRN | 1, |
|
39 offsetof (CMMFCertifiedKeyPair, derPublicationInfo), |
|
40 SEC_ASN1_SUB(SEC_AnyTemplate) }, |
|
41 { 0 } |
|
42 }; |
|
43 |
|
44 const SEC_ASN1Template CMMFPKIStatusInfoTemplate[] = { |
|
45 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFPKIStatusInfo)}, |
|
46 { SEC_ASN1_INTEGER, offsetof(CMMFPKIStatusInfo, status)}, |
|
47 { SEC_ASN1_OPTIONAL | SEC_ASN1_UTF8_STRING, |
|
48 offsetof(CMMFPKIStatusInfo, statusString)}, |
|
49 { SEC_ASN1_OPTIONAL | SEC_ASN1_BIT_STRING, |
|
50 offsetof(CMMFPKIStatusInfo, failInfo)}, |
|
51 { 0 } |
|
52 }; |
|
53 |
|
54 const SEC_ASN1Template CMMFSequenceOfCertsTemplate[] = { |
|
55 { SEC_ASN1_SEQUENCE_OF| SEC_ASN1_XTRN, 0, |
|
56 SEC_ASN1_SUB(SEC_SignedCertificateTemplate)} |
|
57 }; |
|
58 |
|
59 const SEC_ASN1Template CMMFRandTemplate[] = { |
|
60 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFRand)}, |
|
61 { SEC_ASN1_INTEGER, offsetof(CMMFRand, integer)}, |
|
62 { SEC_ASN1_OCTET_STRING, offsetof(CMMFRand, senderHash)}, |
|
63 { 0 } |
|
64 }; |
|
65 |
|
66 const SEC_ASN1Template CMMFPOPODecKeyRespContentTemplate[] = { |
|
67 { SEC_ASN1_SEQUENCE_OF | SEC_ASN1_XTRN, |
|
68 offsetof(CMMFPOPODecKeyRespContent, responses), |
|
69 SEC_ASN1_SUB(SEC_IntegerTemplate), |
|
70 sizeof(CMMFPOPODecKeyRespContent)}, |
|
71 { 0 } |
|
72 }; |
|
73 |
|
74 const SEC_ASN1Template CMMFCertOrEncCertEncryptedCertTemplate[] = { |
|
75 { SEC_ASN1_CONTEXT_SPECIFIC | 1, |
|
76 0, |
|
77 CRMFEncryptedValueTemplate}, |
|
78 { 0 } |
|
79 }; |
|
80 |
|
81 const SEC_ASN1Template CMMFCertOrEncCertCertificateTemplate[] = { |
|
82 { SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0, |
|
83 0, |
|
84 SEC_ASN1_SUB(SEC_SignedCertificateTemplate)}, |
|
85 { 0 } |
|
86 }; |
|
87 |
|
88 const SEC_ASN1Template CMMFCertRepContentTemplate[] = { |
|
89 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFCertRepContent)}, |
|
90 { SEC_ASN1_CONSTRUCTED | SEC_ASN1_OPTIONAL | |
|
91 SEC_ASN1_CONTEXT_SPECIFIC | 1, |
|
92 offsetof(CMMFCertRepContent, caPubs), |
|
93 CMMFSequenceOfCertsTemplate }, |
|
94 { SEC_ASN1_SEQUENCE_OF, offsetof(CMMFCertRepContent, response), |
|
95 CMMFCertResponseTemplate}, |
|
96 { 0 } |
|
97 }; |
|
98 |
|
99 static const SEC_ASN1Template CMMFChallengeTemplate[] = { |
|
100 { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CMMFChallenge)}, |
|
101 { SEC_ASN1_POINTER | SEC_ASN1_OPTIONAL | SEC_ASN1_XTRN, |
|
102 offsetof(CMMFChallenge, owf), |
|
103 SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) }, |
|
104 { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, witness) }, |
|
105 { SEC_ASN1_ANY, offsetof(CMMFChallenge, senderDER) }, |
|
106 { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, key) }, |
|
107 { SEC_ASN1_OCTET_STRING, offsetof(CMMFChallenge, challenge) }, |
|
108 { 0 } |
|
109 }; |
|
110 |
|
111 const SEC_ASN1Template CMMFPOPODecKeyChallContentTemplate[] = { |
|
112 { SEC_ASN1_SEQUENCE_OF,offsetof(CMMFPOPODecKeyChallContent, challenges), |
|
113 CMMFChallengeTemplate, sizeof(CMMFPOPODecKeyChallContent) }, |
|
114 { 0 } |
|
115 }; |
|
116 |
|
117 SECStatus |
|
118 cmmf_decode_process_cert_response(PLArenaPool *poolp, |
|
119 CERTCertDBHandle *db, |
|
120 CMMFCertResponse *inCertResp) |
|
121 { |
|
122 SECStatus rv = SECSuccess; |
|
123 |
|
124 if (inCertResp->certifiedKeyPair != NULL) { |
|
125 rv = cmmf_decode_process_certified_key_pair(poolp, |
|
126 db, |
|
127 inCertResp->certifiedKeyPair); |
|
128 } |
|
129 return rv; |
|
130 } |
|
131 |
|
132 static CERTCertificate* |
|
133 cmmf_DecodeDERCertificate(CERTCertDBHandle *db, SECItem *derCert) |
|
134 { |
|
135 CERTCertificate *newCert; |
|
136 |
|
137 newCert = CERT_NewTempCertificate(db, derCert, NULL, PR_FALSE, PR_TRUE); |
|
138 return newCert; |
|
139 } |
|
140 |
|
141 static CMMFCertOrEncCertChoice |
|
142 cmmf_get_certorenccertchoice_from_der(SECItem *der) |
|
143 { |
|
144 CMMFCertOrEncCertChoice retChoice; |
|
145 |
|
146 switch(der->data[0] & 0x0f) { |
|
147 case 0: |
|
148 retChoice = cmmfCertificate; |
|
149 break; |
|
150 case 1: |
|
151 retChoice = cmmfEncryptedCert; |
|
152 break; |
|
153 default: |
|
154 retChoice = cmmfNoCertOrEncCert; |
|
155 break; |
|
156 } |
|
157 return retChoice; |
|
158 } |
|
159 |
|
160 static SECStatus |
|
161 cmmf_decode_process_certorenccert(PLArenaPool *poolp, |
|
162 CERTCertDBHandle *db, |
|
163 CMMFCertOrEncCert *inCertOrEncCert) |
|
164 { |
|
165 SECStatus rv = SECSuccess; |
|
166 |
|
167 inCertOrEncCert->choice = |
|
168 cmmf_get_certorenccertchoice_from_der(&inCertOrEncCert->derValue); |
|
169 |
|
170 switch (inCertOrEncCert->choice) { |
|
171 case cmmfCertificate: |
|
172 { |
|
173 /* The DER has implicit tagging, so we gotta switch it to |
|
174 * un-tagged in order for the ASN1 parser to understand it. |
|
175 * Saving the bits that were changed. |
|
176 */ |
|
177 inCertOrEncCert->derValue.data[0] = 0x30; |
|
178 inCertOrEncCert->cert.certificate = |
|
179 cmmf_DecodeDERCertificate(db, &inCertOrEncCert->derValue); |
|
180 if (inCertOrEncCert->cert.certificate == NULL) { |
|
181 rv = SECFailure; |
|
182 } |
|
183 |
|
184 } |
|
185 break; |
|
186 case cmmfEncryptedCert: |
|
187 PORT_Assert(poolp); |
|
188 if (!poolp) { |
|
189 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
190 rv = SECFailure; |
|
191 break; |
|
192 } |
|
193 inCertOrEncCert->cert.encryptedCert = |
|
194 PORT_ArenaZNew(poolp, CRMFEncryptedValue); |
|
195 if (inCertOrEncCert->cert.encryptedCert == NULL) { |
|
196 rv = SECFailure; |
|
197 break; |
|
198 } |
|
199 rv = SEC_ASN1Decode(poolp, inCertOrEncCert->cert.encryptedCert, |
|
200 CMMFCertOrEncCertEncryptedCertTemplate, |
|
201 (const char*)inCertOrEncCert->derValue.data, |
|
202 inCertOrEncCert->derValue.len); |
|
203 break; |
|
204 default: |
|
205 rv = SECFailure; |
|
206 } |
|
207 return rv; |
|
208 } |
|
209 |
|
210 SECStatus |
|
211 cmmf_decode_process_certified_key_pair(PLArenaPool *poolp, |
|
212 CERTCertDBHandle *db, |
|
213 CMMFCertifiedKeyPair *inCertKeyPair) |
|
214 { |
|
215 return cmmf_decode_process_certorenccert (poolp, |
|
216 db, |
|
217 &inCertKeyPair->certOrEncCert); |
|
218 } |
|
219 |
|
220 |