~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/lib/certhigh/certreq.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

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