summaryrefslogtreecommitdiffstats
path: root/crypto/ct/ct_b64.c
diff options
context:
space:
mode:
authorRob Percival <robpercival@google.com>2016-02-25 13:33:48 +0000
committerRich Salz <rsalz@openssl.org>2016-03-01 11:59:28 -0500
commit8c6afbc55cc8e2d036c0af5adbaff82d8117c6b2 (patch)
tree29f5feb6cf77df46204d65a6dcb6e1af65aedb06 /crypto/ct/ct_b64.c
parent09375d12fb684c6991c06b473664a0630b8b2edf (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.c213
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;
+}