/src/openssl/crypto/ct/ct_vfy.c
Line | Count | Source (jump to first uncovered line) |
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_locl.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 | 0 | { |
31 | 0 | unsigned char tmpbuf[12]; |
32 | 0 | unsigned char *p, *der; |
33 | 0 | size_t derlen; |
34 | 0 | /*+ |
35 | 0 | * digitally-signed struct { |
36 | 0 | * (1 byte) Version sct_version; |
37 | 0 | * (1 byte) SignatureType signature_type = certificate_timestamp; |
38 | 0 | * (8 bytes) uint64 timestamp; |
39 | 0 | * (2 bytes) LogEntryType entry_type; |
40 | 0 | * (? bytes) select(entry_type) { |
41 | 0 | * case x509_entry: ASN.1Cert; |
42 | 0 | * case precert_entry: PreCert; |
43 | 0 | * } signed_entry; |
44 | 0 | * (2 bytes + sct->ext_len) CtExtensions extensions; |
45 | 0 | * } |
46 | 0 | */ |
47 | 0 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET) |
48 | 0 | return 0; |
49 | 0 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL) |
50 | 0 | return 0; |
51 | 0 | |
52 | 0 | p = tmpbuf; |
53 | 0 | *p++ = sct->version; |
54 | 0 | *p++ = SIGNATURE_TYPE_CERT_TIMESTAMP; |
55 | 0 | l2n8(sct->timestamp, p); |
56 | 0 | s2n(sct->entry_type, p); |
57 | 0 |
|
58 | 0 | if (!EVP_DigestUpdate(ctx, tmpbuf, p - tmpbuf)) |
59 | 0 | return 0; |
60 | 0 | |
61 | 0 | if (sct->entry_type == CT_LOG_ENTRY_TYPE_X509) { |
62 | 0 | der = sctx->certder; |
63 | 0 | derlen = sctx->certderlen; |
64 | 0 | } else { |
65 | 0 | if (!EVP_DigestUpdate(ctx, sctx->ihash, sctx->ihashlen)) |
66 | 0 | return 0; |
67 | 0 | der = sctx->preder; |
68 | 0 | derlen = sctx->prederlen; |
69 | 0 | } |
70 | 0 |
|
71 | 0 | /* If no encoding available, fatal error */ |
72 | 0 | if (der == NULL) |
73 | 0 | return 0; |
74 | 0 | |
75 | 0 | /* Include length first */ |
76 | 0 | p = tmpbuf; |
77 | 0 | l2n3(derlen, p); |
78 | 0 |
|
79 | 0 | if (!EVP_DigestUpdate(ctx, tmpbuf, 3)) |
80 | 0 | return 0; |
81 | 0 | if (!EVP_DigestUpdate(ctx, der, derlen)) |
82 | 0 | return 0; |
83 | 0 | |
84 | 0 | /* Add any extensions */ |
85 | 0 | p = tmpbuf; |
86 | 0 | s2n(sct->ext_len, p); |
87 | 0 | if (!EVP_DigestUpdate(ctx, tmpbuf, 2)) |
88 | 0 | return 0; |
89 | 0 | |
90 | 0 | if (sct->ext_len && !EVP_DigestUpdate(ctx, sct->ext, sct->ext_len)) |
91 | 0 | return 0; |
92 | 0 | |
93 | 0 | return 1; |
94 | 0 | } |
95 | | |
96 | | int SCT_CTX_verify(const SCT_CTX *sctx, const SCT *sct) |
97 | 0 | { |
98 | 0 | EVP_MD_CTX *ctx = NULL; |
99 | 0 | int ret = 0; |
100 | 0 |
|
101 | 0 | if (!SCT_is_complete(sct) || sctx->pkey == NULL || |
102 | 0 | sct->entry_type == CT_LOG_ENTRY_TYPE_NOT_SET || |
103 | 0 | (sct->entry_type == CT_LOG_ENTRY_TYPE_PRECERT && sctx->ihash == NULL)) { |
104 | 0 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_NOT_SET); |
105 | 0 | return 0; |
106 | 0 | } |
107 | 0 | if (sct->version != SCT_VERSION_V1) { |
108 | 0 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_UNSUPPORTED_VERSION); |
109 | 0 | return 0; |
110 | 0 | } |
111 | 0 | if (sct->log_id_len != sctx->pkeyhashlen || |
112 | 0 | memcmp(sct->log_id, sctx->pkeyhash, sctx->pkeyhashlen) != 0) { |
113 | 0 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_LOG_ID_MISMATCH); |
114 | 0 | return 0; |
115 | 0 | } |
116 | 0 | if (sct->timestamp > sctx->epoch_time_in_ms) { |
117 | 0 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_FUTURE_TIMESTAMP); |
118 | 0 | return 0; |
119 | 0 | } |
120 | 0 |
|
121 | 0 | ctx = EVP_MD_CTX_new(); |
122 | 0 | if (ctx == NULL) |
123 | 0 | goto end; |
124 | 0 | |
125 | 0 | if (!EVP_DigestVerifyInit(ctx, NULL, EVP_sha256(), NULL, sctx->pkey)) |
126 | 0 | goto end; |
127 | 0 | |
128 | 0 | if (!sct_ctx_update(ctx, sctx, sct)) |
129 | 0 | goto end; |
130 | 0 | |
131 | 0 | /* Verify signature */ |
132 | 0 | ret = EVP_DigestVerifyFinal(ctx, sct->sig, sct->sig_len); |
133 | 0 | /* If ret < 0 some other error: fall through without setting error */ |
134 | 0 | if (ret == 0) |
135 | 0 | CTerr(CT_F_SCT_CTX_VERIFY, CT_R_SCT_INVALID_SIGNATURE); |
136 | 0 |
|
137 | 0 | end: |
138 | 0 | EVP_MD_CTX_free(ctx); |
139 | 0 | return ret; |
140 | 0 | } |