GH620: second diff from rt-2275, adds error code
[openssl.git] / crypto / x509v3 / v3_scts.c
1 /*
2  * Written by Rob Stradling (rob@comodo.com) for the OpenSSL project 2014.
3  */
4 /* ====================================================================
5  * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    licensing@OpenSSL.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57
58 #include <stdio.h>
59 #include "internal/cryptlib.h"
60 #include <openssl/asn1.h>
61 #include <openssl/x509v3.h>
62 #include "ext_dat.h"
63 #include "internal/ct_int.h"
64
65 #ifndef OPENSSL_NO_CT
66 /* Signature and hash algorithms from RFC 5246 */
67 #define TLSEXT_hash_sha256                              4
68
69 #define TLSEXT_signature_rsa                            1
70 #define TLSEXT_signature_ecdsa                          3
71
72
73 #define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
74                             (((unsigned int)(c[1]))    )),c+=2)
75
76 #define n2l8(c,l)       (l =((uint64_t)(*((c)++)))<<56, \
77                          l|=((uint64_t)(*((c)++)))<<48, \
78                          l|=((uint64_t)(*((c)++)))<<40, \
79                          l|=((uint64_t)(*((c)++)))<<32, \
80                          l|=((uint64_t)(*((c)++)))<<24, \
81                          l|=((uint64_t)(*((c)++)))<<16, \
82                          l|=((uint64_t)(*((c)++)))<< 8, \
83                          l|=((uint64_t)(*((c)++))))
84
85
86 static void SCT_LIST_free(STACK_OF(SCT) *a);
87 static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a,
88                                    const unsigned char **pp, long length);
89 static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
90                         BIO *out, int indent);
91
92 const X509V3_EXT_METHOD v3_ct_scts[] = {
93     {NID_ct_precert_scts, 0, NULL,
94      0, (X509V3_EXT_FREE)SCT_LIST_free,
95      (X509V3_EXT_D2I)d2i_SCT_LIST, 0,
96      0, 0, 0, 0,
97      (X509V3_EXT_I2R)i2r_SCT_LIST, 0,
98      NULL},
99
100     {NID_ct_cert_scts, 0, NULL,
101      0, (X509V3_EXT_FREE)SCT_LIST_free,
102      (X509V3_EXT_D2I)d2i_SCT_LIST, 0,
103      0, 0, 0, 0,
104      (X509V3_EXT_I2R)i2r_SCT_LIST, 0,
105      NULL},
106 };
107
108 static void tls12_signature_print(BIO *out, const unsigned char hash_alg,
109                                   const unsigned char sig_alg)
110 {
111     int nid = NID_undef;
112     /* RFC6962 only permits two signature algorithms */
113     if (hash_alg == TLSEXT_hash_sha256) {
114         if (sig_alg == TLSEXT_signature_rsa)
115             nid = NID_sha256WithRSAEncryption;
116         else if (sig_alg == TLSEXT_signature_ecdsa)
117             nid = NID_ecdsa_with_SHA256;
118     }
119     if (nid == NID_undef)
120         BIO_printf(out, "%02X%02X", hash_alg, sig_alg);
121     else
122         BIO_printf(out, "%s", OBJ_nid2ln(nid));
123 }
124
125 static void timestamp_print(BIO *out, uint64_t timestamp)
126 {
127     ASN1_GENERALIZEDTIME *gen;
128     char genstr[20];
129     gen = ASN1_GENERALIZEDTIME_new();
130     ASN1_GENERALIZEDTIME_adj(gen, (time_t)0,
131                              (int)(timestamp / 86400000),
132                              (timestamp % 86400000) / 1000);
133     /*
134      * Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15
135      * characters long with a final Z. Update it with fractional seconds.
136      */
137     BIO_snprintf(genstr, sizeof(genstr), "%.14s.%03dZ",
138                  ASN1_STRING_data(gen), (unsigned int)(timestamp % 1000));
139     ASN1_GENERALIZEDTIME_set_string(gen, genstr);
140     ASN1_GENERALIZEDTIME_print(out, gen);
141     ASN1_GENERALIZEDTIME_free(gen);
142 }
143
144 static void SCT_LIST_free(STACK_OF(SCT) *a)
145 {
146     sk_SCT_pop_free(a, SCT_free);
147 }
148
149 static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a,
150                                    const unsigned char **pp, long length)
151 {
152     ASN1_OCTET_STRING *oct = NULL;
153     STACK_OF(SCT) *sk = NULL;
154     SCT *sct;
155     unsigned char *p, *p2;
156     unsigned short listlen, sctlen = 0, fieldlen;
157     const unsigned char *q = *pp;
158
159     if (d2i_ASN1_OCTET_STRING(&oct, &q, length) == NULL)
160         return NULL;
161     if (oct->length < 2)
162         goto done;
163     p = oct->data;
164     n2s(p, listlen);
165     if (listlen != oct->length - 2)
166         goto done;
167
168     if ((sk = sk_SCT_new_null()) == NULL)
169         goto done;
170
171     while (listlen > 0) {
172         if (listlen < 2)
173             goto err;
174         n2s(p, sctlen);
175         listlen -= 2;
176
177         if ((sctlen < 1) || (sctlen > listlen))
178             goto err;
179         listlen -= sctlen;
180
181         sct = OPENSSL_malloc(sizeof(*sct));
182         if (sct == NULL)
183             goto err;
184         if (!sk_SCT_push(sk, sct)) {
185             OPENSSL_free(sct);
186             goto err;
187         }
188
189         sct->sct = OPENSSL_malloc(sctlen);
190         if (sct->sct == NULL)
191             goto err;
192         memcpy(sct->sct, p, sctlen);
193         sct->sct_len = sctlen;
194         p += sctlen;
195         p2 = sct->sct;
196
197         sct->version = *p2++;
198         if (sct->version == 0) { /* SCT v1 */
199             /*-
200              * Fixed-length header:
201              *              struct {
202              * (1 byte)       Version sct_version;
203              * (32 bytes)     LogID id;
204              * (8 bytes)      uint64 timestamp;
205              * (2 bytes + ?)  CtExtensions extensions;
206              */
207             if (sctlen < 43)
208                 goto err;
209             sctlen -= 43;
210
211             sct->log_id = p2;
212             sct->log_id_len = 32;
213             p2 += 32;
214
215             n2l8(p2, sct->timestamp);
216
217             n2s(p2, fieldlen);
218             if (sctlen < fieldlen)
219                 goto err;
220             sct->ext = p2;
221             sct->ext_len = fieldlen;
222             p2 += fieldlen;
223             sctlen -= fieldlen;
224
225             /*-
226              * digitally-signed struct header:
227              * (1 byte)       Hash algorithm
228              * (1 byte)       Signature algorithm
229              * (2 bytes + ?)  Signature
230              */
231             if (sctlen < 4)
232                 goto err;
233             sctlen -= 4;
234
235             sct->hash_alg = *p2++;
236             sct->sig_alg = *p2++;
237             n2s(p2, fieldlen);
238             if (sctlen != fieldlen)
239                 goto err;
240             sct->sig = p2;
241             sct->sig_len = fieldlen;
242         }
243     }
244
245  done:
246     ASN1_OCTET_STRING_free(oct);
247     *pp = q;
248     return sk;
249
250  err:
251     SCT_LIST_free(sk);
252     sk = NULL;
253     goto done;
254 }
255
256 static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
257                         BIO *out, int indent)
258 {
259     SCT *sct;
260     int i;
261
262     for (i = 0; i < sk_SCT_num(sct_list);) {
263         sct = sk_SCT_value(sct_list, i);
264
265         BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, "");
266         BIO_printf(out, "\n%*sVersion   : ", indent + 4, "");
267
268         if (sct->version == 0) { /* SCT v1 */
269             BIO_printf(out, "v1(0)");
270
271             BIO_printf(out, "\n%*sLog ID    : ", indent + 4, "");
272             BIO_hex_string(out, indent + 16, 16, sct->log_id, sct->log_id_len);
273
274             BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
275             timestamp_print(out, sct->timestamp);
276
277             BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
278             if (sct->ext_len == 0)
279                 BIO_printf(out, "none");
280             else
281                 BIO_hex_string(out, indent + 16, 16, sct->ext, sct->ext_len);
282
283             BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
284             tls12_signature_print(out, sct->hash_alg, sct->sig_alg);
285             BIO_printf(out, "\n%*s            ", indent + 4, "");
286             BIO_hex_string(out, indent + 16, 16, sct->sig, sct->sig_len);
287         } else {                /* Unknown version */
288
289             BIO_printf(out, "unknown\n%*s", indent + 16, "");
290             BIO_hex_string(out, indent + 16, 16, sct->sct, sct->sct_len);
291         }
292
293         if (++i < sk_SCT_num(sct_list))
294             BIO_printf(out, "\n");
295     }
296
297     return 1;
298 }
299 #endif