mark all block comments that need format preserving so that
[openssl.git] / crypto / x509v3 / v3_scts.c
1 /* v3_scts.c */
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
59 #include <stdio.h>
60 #include "cryptlib.h"
61 #include <openssl/asn1.h>
62 #include <openssl/x509v3.h>
63 #include "../ssl/ssl_locl.h"
64
65 #if (defined(_WIN32) || defined(_WIN64)) && !defined(__MINGW32__)
66 #define SCT_TIMESTAMP unsigned __int64
67 #elif defined(__arch64__)
68 #define SCT_TIMESTAMP unsigned long
69 #else
70 #define SCT_TIMESTAMP unsigned long long
71 #endif
72
73 #define n2l8(c,l)       (l =((SCT_TIMESTAMP)(*((c)++)))<<56, \
74                          l|=((SCT_TIMESTAMP)(*((c)++)))<<48, \
75                          l|=((SCT_TIMESTAMP)(*((c)++)))<<40, \
76                          l|=((SCT_TIMESTAMP)(*((c)++)))<<32, \
77                          l|=((SCT_TIMESTAMP)(*((c)++)))<<24, \
78                          l|=((SCT_TIMESTAMP)(*((c)++)))<<16, \
79                          l|=((SCT_TIMESTAMP)(*((c)++)))<< 8, \
80                          l|=((SCT_TIMESTAMP)(*((c)++))))
81
82 typedef struct SCT_st {
83         /* The encoded SCT */
84         unsigned char *sct;
85         unsigned short sctlen;
86
87         /* Components of the SCT.  "logid", "ext" and "sig" point to addresses
88          * inside "sct".
89          */
90         unsigned char version;
91         unsigned char* logid;
92         unsigned short logidlen;
93         SCT_TIMESTAMP timestamp;
94         unsigned char *ext;
95         unsigned short extlen;
96         unsigned char hash_alg;
97         unsigned char sig_alg;
98         unsigned char *sig;
99         unsigned short siglen;
100 } SCT;
101
102 DECLARE_STACK_OF(SCT)
103
104 static void SCT_LIST_free(STACK_OF(SCT) *a);
105 static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
106                                    long length);
107 static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
108                         BIO *out, int indent);
109
110 const X509V3_EXT_METHOD v3_ct_scts[] = {
111 { NID_ct_precert_scts, 0, NULL,
112 0,(X509V3_EXT_FREE)SCT_LIST_free,
113 (X509V3_EXT_D2I)d2i_SCT_LIST, 0,
114 0,0,0,0,
115 (X509V3_EXT_I2R)i2r_SCT_LIST, 0,
116 NULL},
117
118 { NID_ct_cert_scts, 0, NULL,
119 0,(X509V3_EXT_FREE)SCT_LIST_free,
120 (X509V3_EXT_D2I)d2i_SCT_LIST, 0,
121 0,0,0,0,
122 (X509V3_EXT_I2R)i2r_SCT_LIST, 0,
123 NULL},
124 };
125
126 static void tls12_signature_print(BIO *out, const unsigned char hash_alg,
127                                   const unsigned char sig_alg)
128         {
129         int nid = NID_undef;
130         /* RFC6962 only permits two signature algorithms */
131         if (hash_alg == TLSEXT_hash_sha256)
132                 {
133                 if (sig_alg == TLSEXT_signature_rsa)
134                         nid = NID_sha256WithRSAEncryption;
135                 else if (sig_alg == TLSEXT_signature_ecdsa)
136                         nid = NID_ecdsa_with_SHA256;
137                 }
138         if (nid == NID_undef)
139                 BIO_printf(out, "%02X%02X", hash_alg, sig_alg);
140         else
141                 BIO_printf(out, "%s", OBJ_nid2ln(nid));
142         }
143
144 static void timestamp_print(BIO *out, SCT_TIMESTAMP timestamp)
145         {
146         ASN1_GENERALIZEDTIME *gen;
147         char genstr[20];
148         gen = ASN1_GENERALIZEDTIME_new();
149         ASN1_GENERALIZEDTIME_adj(gen, (time_t)0,
150                                         (int)(timestamp / 86400000),
151                                         (timestamp % 86400000) / 1000);
152         /* Note GeneralizedTime from ASN1_GENERALIZETIME_adj is always 15
153          * characters long with a final Z. Update it with fractional seconds.
154          */
155         BIO_snprintf(genstr, sizeof(genstr), "%.14s.%03dZ",
156                                 ASN1_STRING_data(gen),
157                                 (unsigned int)(timestamp % 1000));
158         ASN1_GENERALIZEDTIME_set_string(gen, genstr);
159         ASN1_GENERALIZEDTIME_print(out, gen);
160         ASN1_GENERALIZEDTIME_free(gen);
161         }
162
163 static void SCT_free(SCT *sct)
164         {
165         if (sct)
166                 {
167                 if (sct->sct) OPENSSL_free(sct->sct);
168                 OPENSSL_free(sct);
169                 }
170         }
171
172 static void SCT_LIST_free(STACK_OF(SCT) *a)
173         {
174         sk_SCT_pop_free(a, SCT_free);
175         }
176
177 static STACK_OF(SCT) *d2i_SCT_LIST(STACK_OF(SCT) **a, const unsigned char **pp,
178                                    long length)
179         {
180         ASN1_OCTET_STRING *oct = NULL;
181         STACK_OF(SCT) *sk = NULL;
182         SCT *sct;
183         unsigned char *p, *p2;
184         unsigned short listlen, sctlen = 0, fieldlen;
185
186         if (d2i_ASN1_OCTET_STRING(&oct, pp, length) == NULL)
187                 return NULL;
188         if (oct->length < 2)
189                 goto done;
190         p = oct->data;
191         n2s(p, listlen);
192         if (listlen != oct->length - 2)
193                 goto done;
194
195         if ((sk=sk_SCT_new_null()) == NULL)
196                 goto done;
197
198         while (listlen > 0)
199                 {
200                 if (listlen < 2)
201                         goto err;
202                 n2s(p, sctlen);
203                 listlen -= 2;
204
205                 if ((sctlen < 1) || (sctlen > listlen))
206                         goto err;
207                 listlen -= sctlen;
208
209                 sct = OPENSSL_malloc(sizeof(SCT));
210                 if (!sct)
211                         goto err;
212                 if (!sk_SCT_push(sk, sct))
213                         {
214                         OPENSSL_free(sct);
215                         goto err;
216                         }
217
218                 sct->sct = OPENSSL_malloc(sctlen);
219                 if (!sct->sct)
220                         goto err;
221                 memcpy(sct->sct, p, sctlen);
222                 sct->sctlen = sctlen;
223                 p += sctlen;
224                 p2 = sct->sct;
225
226                 sct->version = *p2++;
227                 if (sct->version == 0)          /* SCT v1 */
228                         {
229                         /*- 
230                          * Fixed-length header:
231                          *              struct {
232                          * (1 byte)       Version sct_version;
233                          * (32 bytes)     LogID id;
234                          * (8 bytes)      uint64 timestamp;
235                          * (2 bytes + ?)  CtExtensions extensions;
236                          */
237                         if (sctlen < 43)
238                                 goto err;
239                         sctlen -= 43;
240
241                         sct->logid = p2;
242                         sct->logidlen = 32;
243                         p2 += 32;
244
245                         n2l8(p2, sct->timestamp);
246
247                         n2s(p2, fieldlen);
248                         if (sctlen < fieldlen)
249                                 goto err;
250                         sct->ext = p2;
251                         sct->extlen = fieldlen;
252                         p2 += fieldlen;
253                         sctlen -= fieldlen;
254
255                         /*-
256                          * digitally-signed struct header:
257                          * (1 byte)       Hash algorithm
258                          * (1 byte)       Signature algorithm
259                          * (2 bytes + ?)  Signature
260                          */
261                         if (sctlen < 4)
262                                 goto err;
263                         sctlen -= 4;
264
265                         sct->hash_alg = *p2++;
266                         sct->sig_alg = *p2++;
267                         n2s(p2, fieldlen);
268                         if (sctlen != fieldlen)
269                                 goto err;
270                         sct->sig = p2;
271                         sct->siglen = fieldlen;
272                         }
273                 }
274
275         done:
276         ASN1_OCTET_STRING_free(oct);
277         return sk;
278
279         err:
280         SCT_LIST_free(sk);
281         sk = NULL;
282         goto done;
283         }
284
285 static int i2r_SCT_LIST(X509V3_EXT_METHOD *method, STACK_OF(SCT) *sct_list,
286                         BIO *out, int indent)
287         {
288         SCT *sct;
289         int i;
290
291         for (i = 0; i < sk_SCT_num(sct_list);) {
292                 sct = sk_SCT_value(sct_list, i);
293
294                 BIO_printf(out, "%*sSigned Certificate Timestamp:", indent, "");
295                 BIO_printf(out, "\n%*sVersion   : ", indent + 4, "");
296
297                 if (sct->version == 0)  /* SCT v1 */
298                         {
299                         BIO_printf(out, "v1(0)");
300
301                         BIO_printf(out, "\n%*sLog ID    : ", indent + 4, "");
302                         BIO_hex_string(out, indent + 16, 16, sct->logid,
303                                        sct->logidlen);
304
305                         BIO_printf(out, "\n%*sTimestamp : ", indent + 4, "");
306                         timestamp_print(out, sct->timestamp);
307
308                         BIO_printf(out, "\n%*sExtensions: ", indent + 4, "");
309                         if (sct->extlen == 0)
310                                 BIO_printf(out, "none");
311                         else
312                                 BIO_hex_string(out, indent + 16, 16, sct->ext,
313                                                sct->extlen);
314
315                         BIO_printf(out, "\n%*sSignature : ", indent + 4, "");
316                         tls12_signature_print(out, sct->hash_alg, sct->sig_alg);
317                         BIO_printf(out, "\n%*s            ", indent + 4, "");
318                         BIO_hex_string(out, indent + 16, 16, sct->sig,
319                                        sct->siglen);
320                         }
321                 else                    /* Unknown version */
322                         {
323                         BIO_printf(out, "unknown\n%*s", indent + 16, "");
324                         BIO_hex_string(out, indent + 16, 16, sct->sct,
325                                        sct->sctlen);
326                         }
327
328                 if (++i < sk_SCT_num(sct_list)) BIO_printf(out, "\n");
329                 }
330
331         return 1;
332         }