comparison nss/lib/certhigh/certreq.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
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 "cert.h"
6 #include "certt.h"
7 #include "secder.h"
8 #include "key.h"
9 #include "secitem.h"
10 #include "secasn1.h"
11 #include "secerr.h"
12
13 SEC_ASN1_MKSUB(SEC_AnyTemplate)
14
15 const SEC_ASN1Template CERT_AttributeTemplate[] = {
16 { SEC_ASN1_SEQUENCE,
17 0, NULL, sizeof(CERTAttribute) },
18 { SEC_ASN1_OBJECT_ID, offsetof(CERTAttribute, attrType) },
19 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(CERTAttribute, attrValue),
20 SEC_ASN1_SUB(SEC_AnyTemplate) },
21 { 0 }
22 };
23
24 const SEC_ASN1Template CERT_SetOfAttributeTemplate[] = {
25 { SEC_ASN1_SET_OF, 0, CERT_AttributeTemplate },
26 };
27
28 const SEC_ASN1Template CERT_CertificateRequestTemplate[] = {
29 { SEC_ASN1_SEQUENCE,
30 0, NULL, sizeof(CERTCertificateRequest) },
31 { SEC_ASN1_INTEGER,
32 offsetof(CERTCertificateRequest,version) },
33 { SEC_ASN1_INLINE,
34 offsetof(CERTCertificateRequest,subject),
35 CERT_NameTemplate },
36 { SEC_ASN1_INLINE,
37 offsetof(CERTCertificateRequest,subjectPublicKeyInfo),
38 CERT_SubjectPublicKeyInfoTemplate },
39 { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
40 offsetof(CERTCertificateRequest,attributes),
41 CERT_SetOfAttributeTemplate },
42 { 0 }
43 };
44
45 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate)
46
47 CERTCertificate *
48 CERT_CreateCertificate(unsigned long serialNumber,
49 CERTName *issuer,
50 CERTValidity *validity,
51 CERTCertificateRequest *req)
52 {
53 CERTCertificate *c;
54 int rv;
55 PLArenaPool *arena;
56
57 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
58
59 if ( !arena ) {
60 return(0);
61 }
62
63 c = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
64
65 if (!c) {
66 PORT_FreeArena(arena, PR_FALSE);
67 return 0;
68 }
69
70 c->referenceCount = 1;
71 c->arena = arena;
72
73 /*
74 * Default is a plain version 1.
75 * If extensions are added, it will get changed as appropriate.
76 */
77 rv = DER_SetUInteger(arena, &c->version, SEC_CERTIFICATE_VERSION_1);
78 if (rv) goto loser;
79
80 rv = DER_SetUInteger(arena, &c->serialNumber, serialNumber);
81 if (rv) goto loser;
82
83 rv = CERT_CopyName(arena, &c->issuer, issuer);
84 if (rv) goto loser;
85
86 rv = CERT_CopyValidity(arena, &c->validity, validity);
87 if (rv) goto loser;
88
89 rv = CERT_CopyName(arena, &c->subject, &req->subject);
90 if (rv) goto loser;
91 rv = SECKEY_CopySubjectPublicKeyInfo(arena, &c->subjectPublicKeyInfo,
92 &req->subjectPublicKeyInfo);
93 if (rv) goto loser;
94
95 return c;
96
97 loser:
98 CERT_DestroyCertificate(c);
99 return 0;
100 }
101
102 /************************************************************************/
103 /* It's clear from the comments that the original author of this
104 * function expected the template for certificate requests to treat
105 * the attributes as a SET OF ANY. This function expected to be
106 * passed an array of SECItems each of which contained an already encoded
107 * Attribute. But the cert request template does not treat the
108 * Attributes as a SET OF ANY, and AFAIK never has. Instead the template
109 * encodes attributes as a SET OF xxxxxxx. That is, it expects to encode
110 * each of the Attributes, not have them pre-encoded. Consequently an
111 * array of SECItems containing encoded Attributes is of no value to this
112 * function. But we cannot change the signature of this public function.
113 * It must continue to take SECItems.
114 *
115 * I have recoded this function so that each SECItem contains an
116 * encoded cert extension. The encoded cert extensions form the list for the
117 * single attribute of the cert request. In this implementation there is at most
118 * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
119 */
120
121 CERTCertificateRequest *
122 CERT_CreateCertificateRequest(CERTName *subject,
123 CERTSubjectPublicKeyInfo *spki,
124 SECItem **attributes)
125 {
126 CERTCertificateRequest *certreq;
127 PLArenaPool *arena;
128 CERTAttribute * attribute;
129 SECOidData * oidData;
130 SECStatus rv;
131 int i = 0;
132
133 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
134 if ( arena == NULL ) {
135 return NULL;
136 }
137
138 certreq = PORT_ArenaZNew(arena, CERTCertificateRequest);
139 if (!certreq) {
140 PORT_FreeArena(arena, PR_FALSE);
141 return NULL;
142 }
143 /* below here it is safe to goto loser */
144
145 certreq->arena = arena;
146
147 rv = DER_SetUInteger(arena, &certreq->version,
148 SEC_CERTIFICATE_REQUEST_VERSION);
149 if (rv != SECSuccess)
150 goto loser;
151
152 rv = CERT_CopyName(arena, &certreq->subject, subject);
153 if (rv != SECSuccess)
154 goto loser;
155
156 rv = SECKEY_CopySubjectPublicKeyInfo(arena,
157 &certreq->subjectPublicKeyInfo,
158 spki);
159 if (rv != SECSuccess)
160 goto loser;
161
162 certreq->attributes = PORT_ArenaZNewArray(arena, CERTAttribute*, 2);
163 if(!certreq->attributes)
164 goto loser;
165
166 /* Copy over attribute information */
167 if (!attributes || !attributes[0]) {
168 /*
169 ** Invent empty attribute information. According to the
170 ** pkcs#10 spec, attributes has this ASN.1 type:
171 **
172 ** attributes [0] IMPLICIT Attributes
173 **
174 ** Which means, we should create a NULL terminated list
175 ** with the first entry being NULL;
176 */
177 certreq->attributes[0] = NULL;
178 return certreq;
179 }
180
181 /* allocate space for attributes */
182 attribute = PORT_ArenaZNew(arena, CERTAttribute);
183 if (!attribute)
184 goto loser;
185
186 oidData = SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST );
187 PORT_Assert(oidData);
188 if (!oidData)
189 goto loser;
190 rv = SECITEM_CopyItem(arena, &attribute->attrType, &oidData->oid);
191 if (rv != SECSuccess)
192 goto loser;
193
194 for (i = 0; attributes[i] != NULL ; i++)
195 ;
196 attribute->attrValue = PORT_ArenaZNewArray(arena, SECItem *, i+1);
197 if (!attribute->attrValue)
198 goto loser;
199
200 /* copy attributes */
201 for (i = 0; attributes[i]; i++) {
202 /*
203 ** Attributes are a SetOf Attribute which implies
204 ** lexigraphical ordering. It is assumes that the
205 ** attributes are passed in sorted. If we need to
206 ** add functionality to sort them, there is an
207 ** example in the PKCS 7 code.
208 */
209 attribute->attrValue[i] = SECITEM_ArenaDupItem(arena, attributes[i]);
210 if(!attribute->attrValue[i])
211 goto loser;
212 }
213
214 certreq->attributes[0] = attribute;
215
216 return certreq;
217
218 loser:
219 CERT_DestroyCertificateRequest(certreq);
220 return NULL;
221 }
222
223 void
224 CERT_DestroyCertificateRequest(CERTCertificateRequest *req)
225 {
226 if (req && req->arena) {
227 PORT_FreeArena(req->arena, PR_FALSE);
228 }
229 return;
230 }
231
232 static void
233 setCRExt(void *o, CERTCertExtension **exts)
234 {
235 ((CERTCertificateRequest *)o)->attributes = (struct CERTAttributeStr **)exts;
236 }
237
238 /*
239 ** Set up to start gathering cert extensions for a cert request.
240 ** The list is created as CertExtensions and converted to an
241 ** attribute list by CERT_FinishCRAttributes().
242 */
243 extern void *cert_StartExtensions(void *owner, PLArenaPool *ownerArena,
244 void (*setExts)(void *object, CERTCertExtension **exts));
245 void *
246 CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req)
247 {
248 return (cert_StartExtensions ((void *)req, req->arena, setCRExt));
249 }
250
251 /*
252 ** At entry req->attributes actually contains an list of cert extensions--
253 ** req-attributes is overloaded until the list is DER encoded (the first
254 ** ...EncodeItem() below).
255 ** We turn this into an attribute list by encapsulating it
256 ** in a PKCS 10 Attribute structure
257 */
258 SECStatus
259 CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req)
260 { SECItem *extlist;
261 SECOidData *oidrec;
262 CERTAttribute *attribute;
263
264 if (!req || !req->arena) {
265 PORT_SetError(SEC_ERROR_INVALID_ARGS);
266 return SECFailure;
267 }
268 if (req->attributes == NULL || req->attributes[0] == NULL)
269 return SECSuccess;
270
271 extlist = SEC_ASN1EncodeItem(req->arena, NULL, &req->attributes,
272 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate));
273 if (extlist == NULL)
274 return(SECFailure);
275
276 oidrec = SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST);
277 if (oidrec == NULL)
278 return SECFailure;
279
280 /* now change the list of cert extensions into a list of attributes
281 */
282 req->attributes = PORT_ArenaZNewArray(req->arena, CERTAttribute*, 2);
283
284 attribute = PORT_ArenaZNew(req->arena, CERTAttribute);
285
286 if (req->attributes == NULL || attribute == NULL ||
287 SECITEM_CopyItem(req->arena, &attribute->attrType, &oidrec->oid) != 0) {
288 PORT_SetError(SEC_ERROR_NO_MEMORY);
289 return SECFailure;
290 }
291 attribute->attrValue = PORT_ArenaZNewArray(req->arena, SECItem*, 2);
292
293 if (attribute->attrValue == NULL)
294 return SECFailure;
295
296 attribute->attrValue[0] = extlist;
297 attribute->attrValue[1] = NULL;
298 req->attributes[0] = attribute;
299 req->attributes[1] = NULL;
300
301 return SECSuccess;
302 }
303
304 SECStatus
305 CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req,
306 CERTCertExtension ***exts)
307 {
308 if (req == NULL || exts == NULL) {
309 PORT_SetError(SEC_ERROR_INVALID_ARGS);
310 return SECFailure;
311 }
312
313 if (req->attributes == NULL || *req->attributes == NULL)
314 return SECSuccess;
315
316 if ((*req->attributes)->attrValue == NULL) {
317 PORT_SetError(SEC_ERROR_INVALID_ARGS);
318 return SECFailure;
319 }
320
321 return(SEC_ASN1DecodeItem(req->arena, exts,
322 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate),
323 (*req->attributes)->attrValue[0]));
324 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)