1 /* 2 * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. 3 * 4 * Licensed under the OpenSSL license (the "License"). You may not use 5 * this file except in compliance with the License. You can obtain a copy 6 * in the file LICENSE in the source distribution or at 7 * https://www.openssl.org/source/license.html 8 */ 9 10 #include <string.h> 11 12 #include <openssl/ct.h> 13 #include <openssl/err.h> 14 #include <openssl/evp.h> 15 #include <openssl/x509.h> 16 17 #include "ct_local.h" 18 19 typedef enum sct_signature_type_t { 20 SIGNATURE_TYPE_NOT_SET = -1, 21 SIGNATURE_TYPE_CERT_TIMESTAMP, 22 SIGNATURE_TYPE_TREE_HASH 23 } SCT_SIGNATURE_TYPE; 24 25 /* 26 * Update encoding for SCT signature verification/generation to supplied 27 * EVP_MD_CTX. 28 */ 29 static int sct_ctx_update(EVP_MD_CTX *ctx, const SCT_CTX *sctx, const SCT *sct) 30 { 31 unsigned char tmpbuf[12]; 32 unsigned char *p, *der; 33 size_t derlen; 34 /*+ 35 * digitally-signed struct { 36 * (1 byte) Version sct_version; 37 * (1 byte) SignatureType signature_type = certificate_timestamp; 38 * (8 bytes) uint64 timestamp; 39 * (2 bytes) LogEntryType entry_type; 40 * (? bytes) select(entry_type) { 41 * case x509_entry: ASN.1Cert; 42 * case precert_entry: PreCert; 43 * } signed_entry; 44 * (2 bytes + sct->ext_len) CtExtensions extensions; 45 * } 46 */ 47 if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) 48 return 0; 49 if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) 50 return 0; 51 52 p = tmpbuf; 53 *p++ = sct->version; 54 *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; 55 l2n8(sct->timestamp, p); 56 s2n(sct->entry_type, p); 57 58 if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) 59 return 0; 60 61 if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { 62 der = sctx->certder; 63 derlen = sctx->certderlen; 64 } else { 65 if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) 66 return 0; 67 der = sctx->preder; 68 derlen = sctx->prederlen; 69 } 70 71 /* If no encoding available, fatal error */ 72 if (der == NULL) 73 return 0; 74 75 /* Include length first */ 76 p = tmpbuf; 77 l2n3(derlen, p); 78 79 if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) 80 return 0; 81 if (!EVP_DigestUpdate(ctx, der, derlen)) 82 return 0; 83 84 /* Add any extensions */ 85 p = tmpbuf; 86 s2n(sct->ext_len, p); 87 if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) 88 return 0; 89 90 if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) 91 return 0; 92 93 return 1; 94 } 95 96 int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) 97 { 98 EVP_MD_CTX *ctx = NULL; 99 int ret = 0; 100 101 if (!SCT_is_complete(sct) || sctx->pkey == NULL || 102 sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || 103 (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { 104 CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); 105 return 0; 106 } 107 if (sct->version != SCT_VERSION_V1) { 108 CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); 109 return 0; 110 } 111 if (sct->log_id_len != sctx->pkeyhashlen || 112 memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { 113 CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); 114 return 0; 115 } 116 if (sct->timestamp > sctx->epoch_time_in_ms) { 117 CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); 118 return 0; 119 } 120 121 ctx = EVP_MD_CTX_new(); 122 if (ctx == NULL) 123 goto end; 124 125 if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) 126 goto end; 127 128 if (!sct_ctx_update(ctx, sctx, sct)) 129 goto end; 130 131 /* Verify signature */ 132 ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); 133 /* If ret < 0 some other error: fall through without setting error */ 134 if (ret == 0) 135 CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); 136 137 end: 138 EVP_MD_CTX_free(ctx); 139 return ret; 140 } 141