Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / security / nss / lib / certhigh / certreq.c
blobfc7a7dd1574498fb62acc542a43ed00c51675f4e
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
37 #include "cert.h"
38 #include "certt.h"
39 #include "secder.h"
40 #include "key.h"
41 #include "secitem.h"
42 #include "secasn1.h"
43 #include "secerr.h"
45 SEC_ASN1_MKSUB(SEC_AnyTemplate)
47 const SEC_ASN1Template CERT_AttributeTemplate[] = {
48 { SEC_ASN1_SEQUENCE,
49 0, NULL, sizeof(CERTAttribute) },
50 { SEC_ASN1_OBJECT_ID, offsetof(CERTAttribute, attrType) },
51 { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(CERTAttribute, attrValue),
52 SEC_ASN1_SUB(SEC_AnyTemplate) },
53 { 0 }
56 const SEC_ASN1Template CERT_SetOfAttributeTemplate[] = {
57 { SEC_ASN1_SET_OF, 0, CERT_AttributeTemplate },
60 const SEC_ASN1Template CERT_CertificateRequestTemplate[] = {
61 { SEC_ASN1_SEQUENCE,
62 0, NULL, sizeof(CERTCertificateRequest) },
63 { SEC_ASN1_INTEGER,
64 offsetof(CERTCertificateRequest,version) },
65 { SEC_ASN1_INLINE,
66 offsetof(CERTCertificateRequest,subject),
67 CERT_NameTemplate },
68 { SEC_ASN1_INLINE,
69 offsetof(CERTCertificateRequest,subjectPublicKeyInfo),
70 CERT_SubjectPublicKeyInfoTemplate },
71 { SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
72 offsetof(CERTCertificateRequest,attributes),
73 CERT_SetOfAttributeTemplate },
74 { 0 }
77 SEC_ASN1_CHOOSER_IMPLEMENT(CERT_CertificateRequestTemplate)
79 CERTCertificate *
80 CERT_CreateCertificate(unsigned long serialNumber,
81 CERTName *issuer,
82 CERTValidity *validity,
83 CERTCertificateRequest *req)
85 CERTCertificate *c;
86 int rv;
87 PRArenaPool *arena;
89 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
91 if ( !arena ) {
92 return(0);
95 c = (CERTCertificate *)PORT_ArenaZAlloc(arena, sizeof(CERTCertificate));
97 if (c) {
98 c->referenceCount = 1;
99 c->arena = arena;
102 * Default is a plain version 1.
103 * If extensions are added, it will get changed as appropriate.
105 rv = DER_SetUInteger(arena, &c->version, SEC_CERTIFICATE_VERSION_1);
106 if (rv) goto loser;
108 rv = DER_SetUInteger(arena, &c->serialNumber, serialNumber);
109 if (rv) goto loser;
111 rv = CERT_CopyName(arena, &c->issuer, issuer);
112 if (rv) goto loser;
114 rv = CERT_CopyValidity(arena, &c->validity, validity);
115 if (rv) goto loser;
117 rv = CERT_CopyName(arena, &c->subject, &req->subject);
118 if (rv) goto loser;
119 rv = SECKEY_CopySubjectPublicKeyInfo(arena, &c->subjectPublicKeyInfo,
120 &req->subjectPublicKeyInfo);
121 if (rv) goto loser;
123 return c;
125 loser:
126 CERT_DestroyCertificate(c);
127 return 0;
130 /************************************************************************/
131 /* It's clear from the comments that the original author of this
132 * function expected the template for certificate requests to treat
133 * the attributes as a SET OF ANY. This function expected to be
134 * passed an array of SECItems each of which contained an already encoded
135 * Attribute. But the cert request template does not treat the
136 * Attributes as a SET OF ANY, and AFAIK never has. Instead the template
137 * encodes attributes as a SET OF xxxxxxx. That is, it expects to encode
138 * each of the Attributes, not have them pre-encoded. Consequently an
139 * array of SECItems containing encoded Attributes is of no value to this
140 * function. But we cannot change the signature of this public function.
141 * It must continue to take SECItems.
143 * I have recoded this function so that each SECItem contains an
144 * encoded cert extension. The encoded cert extensions form the list for the
145 * single attribute of the cert request. In this implementation there is at most
146 * one attribute and it is always of type SEC_OID_PKCS9_EXTENSION_REQUEST.
149 CERTCertificateRequest *
150 CERT_CreateCertificateRequest(CERTName *subject,
151 CERTSubjectPublicKeyInfo *spki,
152 SECItem **attributes)
154 CERTCertificateRequest *certreq;
155 PRArenaPool *arena;
156 CERTAttribute * attribute;
157 SECOidData * oidData;
158 SECStatus rv;
159 int i = 0;
161 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
162 if ( arena == NULL ) {
163 return NULL;
166 certreq = PORT_ArenaZNew(arena, CERTCertificateRequest);
167 if (!certreq) {
168 PORT_FreeArena(arena, PR_FALSE);
169 return NULL;
171 /* below here it is safe to goto loser */
173 certreq->arena = arena;
175 rv = DER_SetUInteger(arena, &certreq->version,
176 SEC_CERTIFICATE_REQUEST_VERSION);
177 if (rv != SECSuccess)
178 goto loser;
180 rv = CERT_CopyName(arena, &certreq->subject, subject);
181 if (rv != SECSuccess)
182 goto loser;
184 rv = SECKEY_CopySubjectPublicKeyInfo(arena,
185 &certreq->subjectPublicKeyInfo,
186 spki);
187 if (rv != SECSuccess)
188 goto loser;
190 certreq->attributes = PORT_ArenaZNewArray(arena, CERTAttribute*, 2);
191 if(!certreq->attributes)
192 goto loser;
194 /* Copy over attribute information */
195 if (!attributes || !attributes[0]) {
197 ** Invent empty attribute information. According to the
198 ** pkcs#10 spec, attributes has this ASN.1 type:
200 ** attributes [0] IMPLICIT Attributes
202 ** Which means, we should create a NULL terminated list
203 ** with the first entry being NULL;
205 certreq->attributes[0] = NULL;
206 return certreq;
209 /* allocate space for attributes */
210 attribute = PORT_ArenaZNew(arena, CERTAttribute);
211 if (!attribute)
212 goto loser;
214 oidData = SECOID_FindOIDByTag( SEC_OID_PKCS9_EXTENSION_REQUEST );
215 PORT_Assert(oidData);
216 if (!oidData)
217 goto loser;
218 rv = SECITEM_CopyItem(arena, &attribute->attrType, &oidData->oid);
219 if (rv != SECSuccess)
220 goto loser;
222 for (i = 0; attributes[i] != NULL ; i++)
224 attribute->attrValue = PORT_ArenaZNewArray(arena, SECItem *, i+1);
225 if (!attribute->attrValue)
226 goto loser;
228 /* copy attributes */
229 for (i = 0; attributes[i]; i++) {
231 ** Attributes are a SetOf Attribute which implies
232 ** lexigraphical ordering. It is assumes that the
233 ** attributes are passed in sorted. If we need to
234 ** add functionality to sort them, there is an
235 ** example in the PKCS 7 code.
237 attribute->attrValue[i] = SECITEM_ArenaDupItem(arena, attributes[i]);
238 if(!attribute->attrValue[i])
239 goto loser;
242 certreq->attributes[0] = attribute;
244 return certreq;
246 loser:
247 CERT_DestroyCertificateRequest(certreq);
248 return NULL;
251 void
252 CERT_DestroyCertificateRequest(CERTCertificateRequest *req)
254 if (req && req->arena) {
255 PORT_FreeArena(req->arena, PR_FALSE);
257 return;
260 static void
261 setCRExt(void *o, CERTCertExtension **exts)
263 ((CERTCertificateRequest *)o)->attributes = (struct CERTAttributeStr **)exts;
267 ** Set up to start gathering cert extensions for a cert request.
268 ** The list is created as CertExtensions and converted to an
269 ** attribute list by CERT_FinishCRAttributes().
271 extern void *cert_StartExtensions(void *owner, PRArenaPool *ownerArena,
272 void (*setExts)(void *object, CERTCertExtension **exts));
273 void *
274 CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req)
276 return (cert_StartExtensions ((void *)req, req->arena, setCRExt));
280 ** At entry req->attributes actually contains an list of cert extensions--
281 ** req-attributes is overloaded until the list is DER encoded (the first
282 ** ...EncodeItem() below).
283 ** We turn this into an attribute list by encapsulating it
284 ** in a PKCS 10 Attribute structure
286 SECStatus
287 CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req)
288 { SECItem *extlist;
289 SECOidData *oidrec;
290 CERTAttribute *attribute;
292 if (!req || !req->arena) {
293 PORT_SetError(SEC_ERROR_INVALID_ARGS);
294 return SECFailure;
296 if (req->attributes == NULL || req->attributes[0] == NULL)
297 return SECSuccess;
299 extlist = SEC_ASN1EncodeItem(req->arena, NULL, &req->attributes,
300 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate));
301 if (extlist == NULL)
302 return(SECFailure);
304 oidrec = SECOID_FindOIDByTag(SEC_OID_PKCS9_EXTENSION_REQUEST);
305 if (oidrec == NULL)
306 return SECFailure;
308 /* now change the list of cert extensions into a list of attributes
310 req->attributes = PORT_ArenaZNewArray(req->arena, CERTAttribute*, 2);
312 attribute = PORT_ArenaZNew(req->arena, CERTAttribute);
314 if (req->attributes == NULL || attribute == NULL ||
315 SECITEM_CopyItem(req->arena, &attribute->attrType, &oidrec->oid) != 0) {
316 PORT_SetError(SEC_ERROR_NO_MEMORY);
317 return SECFailure;
319 attribute->attrValue = PORT_ArenaZNewArray(req->arena, SECItem*, 2);
321 if (attribute->attrValue == NULL)
322 return SECFailure;
324 attribute->attrValue[0] = extlist;
325 attribute->attrValue[1] = NULL;
326 req->attributes[0] = attribute;
327 req->attributes[1] = NULL;
329 return SECSuccess;
332 SECStatus
333 CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req,
334 CERTCertExtension ***exts)
336 if (req == NULL || exts == NULL) {
337 PORT_SetError(SEC_ERROR_INVALID_ARGS);
338 return SECFailure;
341 if (req->attributes == NULL || *req->attributes == NULL)
342 return SECSuccess;
344 if ((*req->attributes)->attrValue == NULL) {
345 PORT_SetError(SEC_ERROR_INVALID_ARGS);
346 return SECFailure;
349 return(SEC_ASN1DecodeItem(req->arena, exts,
350 SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate),
351 (*req->attributes)->attrValue[0]));