diff options
author | Rob Percival <robpercival@google.com> | 2016-02-25 13:33:48 +0000 |
---|---|---|
committer | Rich Salz <rsalz@openssl.org> | 2016-03-01 11:59:28 -0500 |
commit | 8c6afbc55cc8e2d036c0af5adbaff82d8117c6b2 (patch) | |
tree | 29f5feb6cf77df46204d65a6dcb6e1af65aedb06 /crypto/ct/ct_b64.c | |
parent | 09375d12fb684c6991c06b473664a0630b8b2edf (diff) |
Verify SCT signatures
Tests included in future commit, which adds CT policy validation.
Reviewed-by: Ben Laurie <ben@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
Diffstat (limited to 'crypto/ct/ct_b64.c')
-rw-r--r-- | crypto/ct/ct_b64.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/crypto/ct/ct_b64.c b/crypto/ct/ct_b64.c new file mode 100644 index 0000000000..a257b8f0d5 --- /dev/null +++ b/crypto/ct/ct_b64.c @@ -0,0 +1,213 @@ +/* + * Written by Rob Stradling (rob@comodo.com) and Stephen Henson + * (steve@openssl.org) for the OpenSSL project 2014. + */ +/* ==================================================================== + * Copyright (c) 2014 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#include <limits.h> +#include <string.h> + +#include <openssl/ct.h> +#include <openssl/err.h> +#include <openssl/evp.h> + +/* + * TODO(robpercival): These macros are getting duplicated all over the place. + * Is there a single place they should be defined for re-use? + * Also, is there a good reason they aren't functions? + */ +#define n2s(c,s) ((s=(((unsigned int)((c)[0]))<<8) | \ + (((unsigned int)((c)[1])))), \ + c+=2) + +/* + * Decodes the base64 string |in| into |out|. + * A new string will be malloc'd and assigned to |out|. This will be owned by + * the caller. Do not provide a pre-allocated string in |out|. + */ +static int CT_base64_decode(const char *in, unsigned char **out) +{ + size_t inlen; + int outlen; + unsigned char *outbuf = NULL; + + if (in == NULL || out == NULL) { + CTerr(CT_F_CT_BASE64_DECODE, ERR_R_PASSED_NULL_PARAMETER); + goto err; + } + + inlen = strlen(in); + if (inlen == 0) { + *out = NULL; + return 0; + } + + outlen = (inlen / 4) * 3; + outbuf = OPENSSL_malloc(outlen); + if (outbuf == NULL) { + CTerr(CT_F_CT_BASE64_DECODE, ERR_R_MALLOC_FAILURE); + goto err; + } + + outlen = EVP_DecodeBlock(outbuf, (unsigned char *)in, inlen); + if (outlen < 0) { + OPENSSL_free(outbuf); + CTerr(CT_F_CT_BASE64_DECODE, CT_R_BASE64_DECODE_ERROR); + goto err; + } + + *out = outbuf; + return outlen; +err: + OPENSSL_free(outbuf); + return -1; +} + +SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, + ct_log_entry_type_t entry_type, uint64_t timestamp, + const char *extensions_base64, + const char *signature_base64) +{ + SCT *sct; + unsigned char *dec = NULL; + int declen; + + if (logid_base64 == NULL || + extensions_base64 == NULL || + signature_base64 == NULL) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_PASSED_NULL_PARAMETER); + return NULL; + } + + sct = SCT_new(); + if (sct == NULL) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_MALLOC_FAILURE); + return NULL; + } + + /* + * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we + * can only construct SCT versions that have been defined. + */ + if (!SCT_set_version(sct, version)) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, CT_R_SCT_UNSUPPORTED_VERSION); + goto err; + } + + declen = CT_base64_decode(logid_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + if (!SCT_set0_log_id(sct, dec, declen)) + goto err; + dec = NULL; + + declen = CT_base64_decode(extensions_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + SCT_set0_extensions(sct, dec, declen); + dec = NULL; + + declen = CT_base64_decode(signature_base64, &dec); + if (declen < 0) { + CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); + goto err; + } + if (o2i_SCT_signature(sct, (const unsigned char **)&dec, declen) <= 0) + goto err; + + SCT_set_timestamp(sct, timestamp); + + if (!SCT_set_log_entry_type(sct, entry_type)) + goto err; + + return sct; + + err: + OPENSSL_free(dec); + SCT_free(sct); + return NULL; +} + +CTLOG *CTLOG_new_from_base64(const char *pkey_base64, const char *name) +{ + unsigned char *pkey_der; + int pkey_der_len; + EVP_PKEY *pkey = NULL; + CTLOG *log = NULL; + + pkey_der_len = CT_base64_decode(pkey_base64, &pkey_der); + if (pkey_der_len <= 0) { + CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + return NULL; + } + + pkey = d2i_PUBKEY(NULL, (const unsigned char **)&pkey_der, pkey_der_len); + if (pkey == NULL) { + CTerr(CT_F_CTLOG_NEW_FROM_BASE64, CT_R_LOG_CONF_INVALID_KEY); + return NULL; + } + + log = CTLOG_new(pkey, name); + if (log == NULL) { + EVP_PKEY_free(pkey); + return NULL; + } + + return log; +} |