1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2016-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <limits.h>
11e1051a39Sopenharmony_ci#include <string.h>
12e1051a39Sopenharmony_ci
13e1051a39Sopenharmony_ci#include <openssl/ct.h>
14e1051a39Sopenharmony_ci#include <openssl/err.h>
15e1051a39Sopenharmony_ci#include <openssl/evp.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include "ct_local.h"
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci/*
20e1051a39Sopenharmony_ci * Decodes the base64 string |in| into |out|.
21e1051a39Sopenharmony_ci * A new string will be malloc'd and assigned to |out|. This will be owned by
22e1051a39Sopenharmony_ci * the caller. Do not provide a pre-allocated string in |out|.
23e1051a39Sopenharmony_ci */
24e1051a39Sopenharmony_cistatic int ct_base64_decode(const char *in, unsigned char **out)
25e1051a39Sopenharmony_ci{
26e1051a39Sopenharmony_ci    size_t inlen = strlen(in);
27e1051a39Sopenharmony_ci    int outlen, i;
28e1051a39Sopenharmony_ci    unsigned char *outbuf = NULL;
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci    if (inlen == 0) {
31e1051a39Sopenharmony_ci        *out = NULL;
32e1051a39Sopenharmony_ci        return 0;
33e1051a39Sopenharmony_ci    }
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ci    outlen = (inlen / 4) * 3;
36e1051a39Sopenharmony_ci    outbuf = OPENSSL_malloc(outlen);
37e1051a39Sopenharmony_ci    if (outbuf == NULL) {
38e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
39e1051a39Sopenharmony_ci        goto err;
40e1051a39Sopenharmony_ci    }
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci    outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen);
43e1051a39Sopenharmony_ci    if (outlen < 0) {
44e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, CT_R_BASE64_DECODE_ERROR);
45e1051a39Sopenharmony_ci        goto err;
46e1051a39Sopenharmony_ci    }
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ci    /* Subtract padding bytes from |outlen|.  Any more than 2 is malformed. */
49e1051a39Sopenharmony_ci    i = 0;
50e1051a39Sopenharmony_ci    while (in[--inlen] == '=') {
51e1051a39Sopenharmony_ci        --outlen;
52e1051a39Sopenharmony_ci        if (++i > 2)
53e1051a39Sopenharmony_ci            goto err;
54e1051a39Sopenharmony_ci    }
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci    *out = outbuf;
57e1051a39Sopenharmony_ci    return outlen;
58e1051a39Sopenharmony_cierr:
59e1051a39Sopenharmony_ci    OPENSSL_free(outbuf);
60e1051a39Sopenharmony_ci    return -1;
61e1051a39Sopenharmony_ci}
62e1051a39Sopenharmony_ci
63e1051a39Sopenharmony_ciSCT *SCT_new_from_base64(unsigned char version, const char *logid_base64,
64e1051a39Sopenharmony_ci                         ct_log_entry_type_t entry_type, uint64_t timestamp,
65e1051a39Sopenharmony_ci                         const char *extensions_base64,
66e1051a39Sopenharmony_ci                         const char *signature_base64)
67e1051a39Sopenharmony_ci{
68e1051a39Sopenharmony_ci    SCT *sct = SCT_new();
69e1051a39Sopenharmony_ci    unsigned char *dec = NULL;
70e1051a39Sopenharmony_ci    const unsigned char* p = NULL;
71e1051a39Sopenharmony_ci    int declen;
72e1051a39Sopenharmony_ci
73e1051a39Sopenharmony_ci    if (sct == NULL) {
74e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, ERR_R_MALLOC_FAILURE);
75e1051a39Sopenharmony_ci        return NULL;
76e1051a39Sopenharmony_ci    }
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci    /*
79e1051a39Sopenharmony_ci     * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we
80e1051a39Sopenharmony_ci     * can only construct SCT versions that have been defined.
81e1051a39Sopenharmony_ci     */
82e1051a39Sopenharmony_ci    if (!SCT_set_version(sct, version)) {
83e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, CT_R_SCT_UNSUPPORTED_VERSION);
84e1051a39Sopenharmony_ci        goto err;
85e1051a39Sopenharmony_ci    }
86e1051a39Sopenharmony_ci
87e1051a39Sopenharmony_ci    declen = ct_base64_decode(logid_base64, &dec);
88e1051a39Sopenharmony_ci    if (declen < 0) {
89e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
90e1051a39Sopenharmony_ci        goto err;
91e1051a39Sopenharmony_ci    }
92e1051a39Sopenharmony_ci    if (!SCT_set0_log_id(sct, dec, declen))
93e1051a39Sopenharmony_ci        goto err;
94e1051a39Sopenharmony_ci    dec = NULL;
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci    declen = ct_base64_decode(extensions_base64, &dec);
97e1051a39Sopenharmony_ci    if (declen < 0) {
98e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
99e1051a39Sopenharmony_ci        goto err;
100e1051a39Sopenharmony_ci    }
101e1051a39Sopenharmony_ci    SCT_set0_extensions(sct, dec, declen);
102e1051a39Sopenharmony_ci    dec = NULL;
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    declen = ct_base64_decode(signature_base64, &dec);
105e1051a39Sopenharmony_ci    if (declen < 0) {
106e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, X509_R_BASE64_DECODE_ERROR);
107e1051a39Sopenharmony_ci        goto err;
108e1051a39Sopenharmony_ci    }
109e1051a39Sopenharmony_ci
110e1051a39Sopenharmony_ci    p = dec;
111e1051a39Sopenharmony_ci    if (o2i_SCT_signature(sct, &p, declen) <= 0)
112e1051a39Sopenharmony_ci        goto err;
113e1051a39Sopenharmony_ci    OPENSSL_free(dec);
114e1051a39Sopenharmony_ci    dec = NULL;
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    SCT_set_timestamp(sct, timestamp);
117e1051a39Sopenharmony_ci
118e1051a39Sopenharmony_ci    if (!SCT_set_log_entry_type(sct, entry_type))
119e1051a39Sopenharmony_ci        goto err;
120e1051a39Sopenharmony_ci
121e1051a39Sopenharmony_ci    return sct;
122e1051a39Sopenharmony_ci
123e1051a39Sopenharmony_ci err:
124e1051a39Sopenharmony_ci    OPENSSL_free(dec);
125e1051a39Sopenharmony_ci    SCT_free(sct);
126e1051a39Sopenharmony_ci    return NULL;
127e1051a39Sopenharmony_ci}
128e1051a39Sopenharmony_ci
129e1051a39Sopenharmony_ci/*
130e1051a39Sopenharmony_ci * Allocate, build and returns a new |ct_log| from input |pkey_base64|
131e1051a39Sopenharmony_ci * It returns 1 on success,
132e1051a39Sopenharmony_ci * 0 on decoding failure, or invalid parameter if any
133e1051a39Sopenharmony_ci * -1 on internal (malloc) failure
134e1051a39Sopenharmony_ci */
135e1051a39Sopenharmony_ciint CTLOG_new_from_base64_ex(CTLOG **ct_log, const char *pkey_base64,
136e1051a39Sopenharmony_ci                             const char *name, OSSL_LIB_CTX *libctx,
137e1051a39Sopenharmony_ci                             const char *propq)
138e1051a39Sopenharmony_ci{
139e1051a39Sopenharmony_ci    unsigned char *pkey_der = NULL;
140e1051a39Sopenharmony_ci    int pkey_der_len;
141e1051a39Sopenharmony_ci    const unsigned char *p;
142e1051a39Sopenharmony_ci    EVP_PKEY *pkey = NULL;
143e1051a39Sopenharmony_ci
144e1051a39Sopenharmony_ci    if (ct_log == NULL) {
145e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, ERR_R_PASSED_INVALID_ARGUMENT);
146e1051a39Sopenharmony_ci        return 0;
147e1051a39Sopenharmony_ci    }
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    pkey_der_len = ct_base64_decode(pkey_base64, &pkey_der);
150e1051a39Sopenharmony_ci    if (pkey_der_len < 0) {
151e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY);
152e1051a39Sopenharmony_ci        return 0;
153e1051a39Sopenharmony_ci    }
154e1051a39Sopenharmony_ci
155e1051a39Sopenharmony_ci    p = pkey_der;
156e1051a39Sopenharmony_ci    pkey = d2i_PUBKEY_ex(NULL, &p, pkey_der_len, libctx, propq);
157e1051a39Sopenharmony_ci    OPENSSL_free(pkey_der);
158e1051a39Sopenharmony_ci    if (pkey == NULL) {
159e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_CT, CT_R_LOG_CONF_INVALID_KEY);
160e1051a39Sopenharmony_ci        return 0;
161e1051a39Sopenharmony_ci    }
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ci    *ct_log = CTLOG_new_ex(pkey, name, libctx, propq);
164e1051a39Sopenharmony_ci    if (*ct_log == NULL) {
165e1051a39Sopenharmony_ci        EVP_PKEY_free(pkey);
166e1051a39Sopenharmony_ci        return 0;
167e1051a39Sopenharmony_ci    }
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    return 1;
170e1051a39Sopenharmony_ci}
171e1051a39Sopenharmony_ci
172e1051a39Sopenharmony_ciint CTLOG_new_from_base64(CTLOG **ct_log, const char *pkey_base64,
173e1051a39Sopenharmony_ci                          const char *name)
174e1051a39Sopenharmony_ci{
175e1051a39Sopenharmony_ci    return CTLOG_new_from_base64_ex(ct_log, pkey_base64, name, NULL, NULL);
176e1051a39Sopenharmony_ci}
177