d4a32f3f9632c570c3c7a347cb47c88b38ead5e3
[platform/upstream/nss.git] / lib / certdb / xconst.c
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 /*
6  * X.509 Extension Encoding  
7  */
8
9 #include "prtypes.h"
10 #include "seccomon.h"
11 #include "secdert.h"
12 #include "secoidt.h"
13 #include "secasn1t.h"
14 #include "secasn1.h"
15 #include "cert.h"
16 #include "secder.h"
17 #include "prprf.h"
18 #include "xconst.h"
19 #include "genname.h"
20 #include "secasn1.h"
21 #include "secerr.h"
22
23
24 static const SEC_ASN1Template CERTSubjectKeyIDTemplate[] = {
25     { SEC_ASN1_OCTET_STRING }
26 };
27
28
29 static const SEC_ASN1Template CERTIA5TypeTemplate[] = {
30     { SEC_ASN1_IA5_STRING }
31 };
32
33 SEC_ASN1_MKSUB(SEC_GeneralizedTimeTemplate)
34
35 static const SEC_ASN1Template CERTPrivateKeyUsagePeriodTemplate[] = {
36     { SEC_ASN1_SEQUENCE,
37       0, NULL, sizeof(CERTPrivKeyUsagePeriod) },
38     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC  | SEC_ASN1_XTRN | 0,
39           offsetof(CERTPrivKeyUsagePeriod, notBefore), 
40           SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate) },
41     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC  | SEC_ASN1_XTRN | 1,
42           offsetof(CERTPrivKeyUsagePeriod, notAfter), 
43           SEC_ASN1_SUB(SEC_GeneralizedTimeTemplate)},
44     { 0, } 
45 };
46
47
48 const SEC_ASN1Template CERTAltNameTemplate[] = {
49     { SEC_ASN1_CONSTRUCTED, offsetof(CERTAltNameEncodedContext, encodedGenName), 
50       CERT_GeneralNamesTemplate}
51 };
52
53 const SEC_ASN1Template CERTAuthInfoAccessItemTemplate[] = {
54     { SEC_ASN1_SEQUENCE,
55       0, NULL, sizeof(CERTAuthInfoAccess) },
56     { SEC_ASN1_OBJECT_ID,
57       offsetof(CERTAuthInfoAccess, method) },
58     { SEC_ASN1_ANY,
59       offsetof(CERTAuthInfoAccess, derLocation) },
60     { 0, }
61 };
62
63 const SEC_ASN1Template CERTAuthInfoAccessTemplate[] = {
64     { SEC_ASN1_SEQUENCE_OF, 0, CERTAuthInfoAccessItemTemplate }
65 };
66
67
68 SECStatus 
69 CERT_EncodeSubjectKeyID(PLArenaPool *arena, const SECItem* srcString,
70                         SECItem *encodedValue)
71 {
72     SECStatus rv = SECSuccess;
73
74     if (!srcString) {
75         PORT_SetError(SEC_ERROR_INVALID_ARGS);
76         return SECFailure;
77     }
78     if (SEC_ASN1EncodeItem (arena, encodedValue, srcString,
79                             CERTSubjectKeyIDTemplate) == NULL) {
80         rv = SECFailure;
81     }
82     
83     return(rv);
84 }
85
86
87 SECStatus
88 CERT_EncodePrivateKeyUsagePeriod(PLArenaPool *arena,
89                                 CERTPrivKeyUsagePeriod *pkup, 
90                                 SECItem *encodedValue)
91 {
92     SECStatus rv = SECSuccess;
93
94     if (SEC_ASN1EncodeItem (arena, encodedValue, pkup,
95                             CERTPrivateKeyUsagePeriodTemplate) == NULL) {
96         rv = SECFailure;
97     }
98     return(rv);
99 }
100
101 CERTPrivKeyUsagePeriod *
102 CERT_DecodePrivKeyUsagePeriodExtension(PLArenaPool *arena, SECItem *extnValue)
103 {
104     SECStatus rv;
105     CERTPrivKeyUsagePeriod *pPeriod;
106     SECItem newExtnValue;
107
108     /* allocate the certificate policies structure */
109     pPeriod = PORT_ArenaZNew(arena, CERTPrivKeyUsagePeriod);
110     if ( pPeriod == NULL ) {
111         goto loser;
112     }
113     
114     pPeriod->arena = arena;
115
116     /* copy the DER into the arena, since Quick DER returns data that points
117        into the DER input, which may get freed by the caller */
118     rv = SECITEM_CopyItem(arena, &newExtnValue, extnValue);
119     if ( rv != SECSuccess ) {
120         goto loser;
121     }
122
123     rv = SEC_QuickDERDecodeItem(arena, pPeriod, 
124                                 CERTPrivateKeyUsagePeriodTemplate,
125                                 &newExtnValue);
126     if ( rv != SECSuccess ) {
127         goto loser;
128     }
129     return pPeriod;
130     
131 loser:
132     return NULL;
133 }
134
135
136 SECStatus 
137 CERT_EncodeIA5TypeExtension(PLArenaPool *arena, char *value, SECItem *encodedValue)
138 {
139     SECItem encodeContext;
140     SECStatus rv = SECSuccess;
141
142
143     PORT_Memset (&encodeContext, 0, sizeof (encodeContext));
144     
145     if (value != NULL) {
146         encodeContext.data = (unsigned char *)value;
147         encodeContext.len = strlen(value);
148     }
149     if (SEC_ASN1EncodeItem (arena, encodedValue, &encodeContext,
150                             CERTIA5TypeTemplate) == NULL) {
151         rv = SECFailure;
152     }
153     
154     return(rv);
155 }
156
157 SECStatus
158 CERT_EncodeAltNameExtension(PLArenaPool *arena,  CERTGeneralName  *value, SECItem *encodedValue)
159 {
160     SECItem                **encodedGenName;
161     SECStatus              rv = SECSuccess;
162
163     encodedGenName = cert_EncodeGeneralNames(arena, value);
164     if (SEC_ASN1EncodeItem (arena, encodedValue, &encodedGenName,
165                             CERT_GeneralNamesTemplate) == NULL) {
166         rv = SECFailure;
167     }
168
169     return rv;
170 }
171
172 CERTGeneralName *
173 CERT_DecodeAltNameExtension(PLArenaPool *reqArena, SECItem *EncodedAltName)
174 {
175     SECStatus                  rv = SECSuccess;
176     CERTAltNameEncodedContext  encodedContext;
177     SECItem*                   newEncodedAltName;
178
179     if (!reqArena) {
180         PORT_SetError(SEC_ERROR_INVALID_ARGS);
181         return NULL;
182     }
183
184     newEncodedAltName = SECITEM_ArenaDupItem(reqArena, EncodedAltName);
185     if (!newEncodedAltName) {
186         return NULL;
187     }
188
189     encodedContext.encodedGenName = NULL;
190     PORT_Memset(&encodedContext, 0, sizeof(CERTAltNameEncodedContext));
191     rv = SEC_QuickDERDecodeItem (reqArena, &encodedContext,
192                                  CERT_GeneralNamesTemplate, newEncodedAltName);
193     if (rv == SECFailure) {
194         goto loser;
195     }
196     if (encodedContext.encodedGenName && encodedContext.encodedGenName[0])
197         return cert_DecodeGeneralNames(reqArena,
198                                        encodedContext.encodedGenName);
199     /* Extension contained an empty GeneralNames sequence */
200     /* Treat as extension not found */
201     PORT_SetError(SEC_ERROR_EXTENSION_NOT_FOUND);
202 loser:
203     return NULL;
204 }
205
206
207 SECStatus
208 CERT_EncodeNameConstraintsExtension(PLArenaPool          *arena, 
209                                     CERTNameConstraints  *value,
210                                     SECItem              *encodedValue)
211 {
212     SECStatus     rv = SECSuccess;
213     
214     rv = cert_EncodeNameConstraints(value, arena, encodedValue);
215     return rv;
216 }
217
218
219 CERTNameConstraints *
220 CERT_DecodeNameConstraintsExtension(PLArenaPool          *arena,
221                                     const SECItem        *encodedConstraints)
222 {
223     return cert_DecodeNameConstraints(arena, encodedConstraints);
224 }
225
226
227 CERTAuthInfoAccess **
228 CERT_DecodeAuthInfoAccessExtension(PLArenaPool *reqArena,
229                                    SECItem     *encodedExtension)
230 {
231     CERTAuthInfoAccess **info = NULL;
232     SECStatus rv;
233     int i;
234     SECItem* newEncodedExtension;
235
236     if (!reqArena) {
237         PORT_SetError(SEC_ERROR_INVALID_ARGS);
238         return NULL;
239     }
240
241     newEncodedExtension = SECITEM_ArenaDupItem(reqArena, encodedExtension);
242     if (!newEncodedExtension) {
243         return NULL;
244     }
245
246     rv = SEC_QuickDERDecodeItem(reqArena, &info, CERTAuthInfoAccessTemplate, 
247                             newEncodedExtension);
248     if (rv != SECSuccess || info == NULL) {
249         return NULL;
250     }
251
252     for (i = 0; info[i] != NULL; i++) {
253         info[i]->location = CERT_DecodeGeneralName(reqArena,
254                                                    &(info[i]->derLocation),
255                                                    NULL);
256     }
257     return info;
258 }
259
260 SECStatus
261 CERT_EncodeInfoAccessExtension(PLArenaPool *arena,
262                                    CERTAuthInfoAccess **info,
263                                    SECItem *dest)
264 {
265     SECItem *dummy;
266     int i;
267
268     PORT_Assert(info != NULL);
269     PORT_Assert(dest != NULL);
270     if (info == NULL || dest == NULL) {
271         return SECFailure;
272     }
273
274     for (i = 0; info[i] != NULL; i++) {
275         if (CERT_EncodeGeneralName(info[i]->location, &(info[i]->derLocation),
276                                    arena) == NULL)
277             /* Note that this may leave some of the locations filled in. */
278             return SECFailure;
279     }
280     dummy = SEC_ASN1EncodeItem(arena, dest, &info,
281                                CERTAuthInfoAccessTemplate);
282     if (dummy == NULL) {
283         return SECFailure;
284     }
285     return SECSuccess;
286 }