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 v3 Subject Key Usage Extension
7  *
8  */
9 
10 #include "prtypes.h"
11 #include "seccomon.h"
12 #include "secdert.h"
13 #include "secoidt.h"
14 #include "secasn1t.h"
15 #include "secasn1.h"
16 #include "secport.h"
17 #include "certt.h"
18 #include "genname.h"
19 #include "secerr.h"
20 
21 SEC_ASN1_MKSUB(SEC_IntegerTemplate)
22 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
23 
24 const SEC_ASN1Template CERTAuthKeyIDTemplate[] = {
25     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(CERTAuthKeyID) },
26     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 0,
27       offsetof(CERTAuthKeyID, keyID), SEC_ASN1_SUB(SEC_OctetStringTemplate) },
28     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 1,
29       offsetof(CERTAuthKeyID, DERAuthCertIssuer), CERT_GeneralNamesTemplate },
30     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONTEXT_SPECIFIC | SEC_ASN1_XTRN | 2,
31       offsetof(CERTAuthKeyID, authCertSerialNumber),
32       SEC_ASN1_SUB(SEC_IntegerTemplate) },
33     { 0 }
34 };
35 
36 SECStatus
CERT_EncodeAuthKeyID(PLArenaPool * arena,CERTAuthKeyID * value,SECItem * encodedValue)37 CERT_EncodeAuthKeyID(PLArenaPool *arena, CERTAuthKeyID *value,
38                      SECItem *encodedValue)
39 {
40     SECStatus rv = SECFailure;
41 
42     PORT_Assert(value);
43     PORT_Assert(arena);
44     PORT_Assert(value->DERAuthCertIssuer == NULL);
45     PORT_Assert(encodedValue);
46 
47     do {
48 
49         /* If both of the authCertIssuer and the serial number exist, encode
50            the name first.  Otherwise, it is an error if one exist and the other
51            is not.
52          */
53         if (value->authCertIssuer) {
54             if (!value->authCertSerialNumber.data) {
55                 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
56                 break;
57             }
58 
59             value->DERAuthCertIssuer =
60                 cert_EncodeGeneralNames(arena, value->authCertIssuer);
61             if (!value->DERAuthCertIssuer) {
62                 PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
63                 break;
64             }
65         } else if (value->authCertSerialNumber.data) {
66             PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
67             break;
68         }
69 
70         if (SEC_ASN1EncodeItem(arena, encodedValue, value,
71                                CERTAuthKeyIDTemplate) == NULL)
72             break;
73         rv = SECSuccess;
74 
75     } while (0);
76     return (rv);
77 }
78 
79 CERTAuthKeyID *
CERT_DecodeAuthKeyID(PLArenaPool * arena,const SECItem * encodedValue)80 CERT_DecodeAuthKeyID(PLArenaPool *arena, const SECItem *encodedValue)
81 {
82     CERTAuthKeyID *value = NULL;
83     SECStatus rv = SECFailure;
84     void *mark;
85     SECItem newEncodedValue;
86 
87     PORT_Assert(arena);
88 
89     do {
90         mark = PORT_ArenaMark(arena);
91         value = (CERTAuthKeyID *)PORT_ArenaZAlloc(arena, sizeof(*value));
92         if (value == NULL)
93             break;
94         value->DERAuthCertIssuer = NULL;
95         /* copy the DER into the arena, since Quick DER returns data that points
96            into the DER input, which may get freed by the caller */
97         rv = SECITEM_CopyItem(arena, &newEncodedValue, encodedValue);
98         if (rv != SECSuccess) {
99             break;
100         }
101 
102         rv = SEC_QuickDERDecodeItem(arena, value, CERTAuthKeyIDTemplate,
103                                     &newEncodedValue);
104         if (rv != SECSuccess)
105             break;
106 
107         value->authCertIssuer =
108             cert_DecodeGeneralNames(arena, value->DERAuthCertIssuer);
109         if (value->authCertIssuer == NULL)
110             break;
111 
112         /* what if the general name contains other format but not URI ?
113            hl
114          */
115         if ((value->authCertSerialNumber.data && !value->authCertIssuer) ||
116             (!value->authCertSerialNumber.data && value->authCertIssuer)) {
117             PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
118             break;
119         }
120     } while (0);
121 
122     if (rv != SECSuccess) {
123         PORT_ArenaRelease(arena, mark);
124         return ((CERTAuthKeyID *)NULL);
125     }
126     PORT_ArenaUnmark(arena, mark);
127     return (value);
128 }
129