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