summaryrefslogtreecommitdiffstats
path: root/src/crypto/x509
diff options
context:
space:
mode:
authorAdam Langley <agl@google.com>2015-01-22 14:27:53 -0800
committerAdam Langley <agl@google.com>2015-01-30 16:52:14 -0800
commitd9e397b599b13d642138480a28c14db7a136bf05 (patch)
tree34bab61dc4ce323b123ad4614dbc07e86ea2f9ef /src/crypto/x509
downloadexternal_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.zip
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.gz
external_boringssl-d9e397b599b13d642138480a28c14db7a136bf05.tar.bz2
Initial commit of BoringSSL for Android.
Diffstat (limited to 'src/crypto/x509')
-rw-r--r--src/crypto/x509/CMakeLists.txt65
-rw-r--r--src/crypto/x509/a_digest.c97
-rw-r--r--src/crypto/x509/a_sign.c136
-rw-r--r--src/crypto/x509/a_strex.c564
-rw-r--r--src/crypto/x509/a_verify.c133
-rw-r--r--src/crypto/x509/asn1_gen.c862
-rw-r--r--src/crypto/x509/by_dir.c479
-rw-r--r--src/crypto/x509/by_file.c292
-rw-r--r--src/crypto/x509/charmap.h15
-rw-r--r--src/crypto/x509/i2d_pr.c83
-rw-r--r--src/crypto/x509/pkcs7.c154
-rw-r--r--src/crypto/x509/pkcs7_test.c409
-rw-r--r--src/crypto/x509/t_crl.c129
-rw-r--r--src/crypto/x509/t_x509.c500
-rw-r--r--src/crypto/x509/t_x509a.c109
-rw-r--r--src/crypto/x509/vpm_int.h70
-rw-r--r--src/crypto/x509/x509.c152
-rw-r--r--src/crypto/x509/x509_att.c353
-rw-r--r--src/crypto/x509/x509_cmp.c490
-rw-r--r--src/crypto/x509/x509_d2.c105
-rw-r--r--src/crypto/x509/x509_def.c88
-rw-r--r--src/crypto/x509/x509_error.c125
-rw-r--r--src/crypto/x509/x509_ext.c206
-rw-r--r--src/crypto/x509/x509_lu.c740
-rw-r--r--src/crypto/x509/x509_obj.c191
-rw-r--r--src/crypto/x509/x509_r2x.c113
-rw-r--r--src/crypto/x509/x509_req.c313
-rw-r--r--src/crypto/x509/x509_set.c154
-rw-r--r--src/crypto/x509/x509_trs.c304
-rw-r--r--src/crypto/x509/x509_txt.c209
-rw-r--r--src/crypto/x509/x509_v3.c271
-rw-r--r--src/crypto/x509/x509_vfy.c2447
-rw-r--r--src/crypto/x509/x509_vpm.c588
-rw-r--r--src/crypto/x509/x509cset.c165
-rw-r--r--src/crypto/x509/x509name.c381
-rw-r--r--src/crypto/x509/x509rset.c80
-rw-r--r--src/crypto/x509/x509spki.c135
-rw-r--r--src/crypto/x509/x509type.c128
-rw-r--r--src/crypto/x509/x_algor.c154
-rw-r--r--src/crypto/x509/x_all.c544
-rw-r--r--src/crypto/x509/x_attrib.c117
-rw-r--r--src/crypto/x509/x_crl.c545
-rw-r--r--src/crypto/x509/x_exten.c75
-rw-r--r--src/crypto/x509/x_info.c110
-rw-r--r--src/crypto/x509/x_name.c533
-rw-r--r--src/crypto/x509/x_pkey.c105
-rw-r--r--src/crypto/x509/x_pubkey.c373
-rw-r--r--src/crypto/x509/x_req.c112
-rw-r--r--src/crypto/x509/x_sig.c69
-rw-r--r--src/crypto/x509/x_spki.c78
-rw-r--r--src/crypto/x509/x_val.c69
-rw-r--r--src/crypto/x509/x_x509.c209
-rw-r--r--src/crypto/x509/x_x509a.c177
53 files changed, 15105 insertions, 0 deletions
diff --git a/src/crypto/x509/CMakeLists.txt b/src/crypto/x509/CMakeLists.txt
new file mode 100644
index 0000000..f00e28a
--- /dev/null
+++ b/src/crypto/x509/CMakeLists.txt
@@ -0,0 +1,65 @@
+include_directories(. .. ../../include)
+
+add_library(
+ x509
+
+ OBJECT
+
+ a_digest.c
+ a_sign.c
+ a_strex.c
+ a_verify.c
+ asn1_gen.c
+ by_dir.c
+ by_file.c
+ i2d_pr.c
+ pkcs7.c
+ t_crl.c
+ t_x509.c
+ t_x509a.c
+ x509.c
+ x509_att.c
+ x509_cmp.c
+ x509_d2.c
+ x509_def.c
+ x509_error.c
+ x509_ext.c
+ x509_lu.c
+ x509_obj.c
+ x509_r2x.c
+ x509_req.c
+ x509_set.c
+ x509_trs.c
+ x509_txt.c
+ x509_v3.c
+ x509_vfy.c
+ x509_vpm.c
+ x509cset.c
+ x509name.c
+ x509rset.c
+ x509spki.c
+ x509type.c
+ x_algor.c
+ x_all.c
+ x_attrib.c
+ x_crl.c
+ x_exten.c
+ x_info.c
+ x_name.c
+ x_pkey.c
+ x_pubkey.c
+ x_req.c
+ x_sig.c
+ x_spki.c
+ x_val.c
+ x_x509.c
+ x_x509a.c
+)
+
+add_executable(
+ pkcs7_test
+
+ pkcs7_test.c
+)
+
+target_link_libraries(pkcs7_test crypto)
diff --git a/src/crypto/x509/a_digest.c b/src/crypto/x509/a_digest.c
new file mode 100644
index 0000000..6060bbd
--- /dev/null
+++ b/src/crypto/x509/a_digest.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
+ unsigned char *md, unsigned int *len)
+ {
+ int i, ret;
+ unsigned char *str,*p;
+
+ i=i2d(data,NULL);
+ if ((str=(unsigned char *)OPENSSL_malloc(i)) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_digest, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ p=str;
+ i2d(data,&p);
+
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+ }
+
+int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
+ unsigned char *md, unsigned int *len)
+ {
+ int i, ret;
+ unsigned char *str = NULL;
+
+ i=ASN1_item_i2d(asn,&str, it);
+ if (!str) return(0);
+
+ ret = EVP_Digest(str, i, md, len, type, NULL);
+ OPENSSL_free(str);
+ return ret;
+ }
diff --git a/src/crypto/x509/a_sign.c b/src/crypto/x509/a_sign.c
new file mode 100644
index 0000000..f219c23
--- /dev/null
+++ b/src/crypto/x509/a_sign.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.h"
+
+
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
+ const EVP_MD *type)
+ {
+ EVP_MD_CTX ctx;
+ EVP_MD_CTX_init(&ctx);
+ if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
+ {
+ EVP_MD_CTX_cleanup(&ctx);
+ return 0;
+ }
+ return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+ }
+
+
+int ASN1_item_sign_ctx(const ASN1_ITEM *it,
+ X509_ALGOR *algor1, X509_ALGOR *algor2,
+ ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+ {
+ EVP_PKEY *pkey;
+ unsigned char *buf_in=NULL,*buf_out=NULL;
+ size_t inl=0,outl=0,outll=0;
+
+ pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+
+ /* Write out the requested copies of the AlgorithmIdentifier. */
+ if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1))
+ {
+ goto err;
+ }
+ if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2))
+ {
+ goto err;
+ }
+
+ inl=ASN1_item_i2d(asn,&buf_in, it);
+ outll=outl=EVP_PKEY_size(pkey);
+ buf_out=OPENSSL_malloc((unsigned int)outl);
+ if ((buf_in == NULL) || (buf_out == NULL))
+ {
+ outl=0;
+ OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
+ || !EVP_DigestSignFinal(ctx, buf_out, &outl))
+ {
+ outl=0;
+ OPENSSL_PUT_ERROR(X509, ASN1_item_sign_ctx, ERR_R_EVP_LIB);
+ goto err;
+ }
+ if (signature->data != NULL) OPENSSL_free(signature->data);
+ signature->data=buf_out;
+ buf_out=NULL;
+ signature->length=outl;
+ /* In the interests of compatibility, I'll make sure that
+ * the bit string has a 'not-used bits' value of 0
+ */
+ signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+err:
+ EVP_MD_CTX_cleanup(ctx);
+ if (buf_in != NULL)
+ { OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
+ if (buf_out != NULL)
+ { OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
+ return(outl);
+ }
diff --git a/src/crypto/x509/a_strex.c b/src/crypto/x509/a_strex.c
new file mode 100644
index 0000000..b194d18
--- /dev/null
+++ b/src/crypto/x509/a_strex.c
@@ -0,0 +1,564 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "charmap.h"
+
+
+/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
+ * Enhanced string and name printing routines handling
+ * multibyte characters, RFC2253 and a host of other
+ * options.
+ */
+
+
+#define CHARTYPE_BS_ESC (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
+
+#define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
+ ASN1_STRFLGS_ESC_QUOTE | \
+ ASN1_STRFLGS_ESC_CTRL | \
+ ASN1_STRFLGS_ESC_MSB)
+
+
+static int send_bio_chars(void *arg, const void *buf, int len)
+{
+ if(!arg) return 1;
+ if(BIO_write(arg, buf, len) != len) return 0;
+ return 1;
+}
+
+static int send_fp_chars(void *arg, const void *buf, int len)
+{
+ if(!arg) return 1;
+ if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0;
+ return 1;
+}
+
+typedef int char_io(void *arg, const void *buf, int len);
+
+/* This function handles display of
+ * strings, one character at a time.
+ * It is passed an unsigned long for each
+ * character because it could come from 2 or even
+ * 4 byte forms.
+ */
+
+#define HEX_SIZE(type) (sizeof(type)*2)
+
+static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg)
+{
+ unsigned char chflgs, chtmp;
+ char tmphex[HEX_SIZE(long)+3];
+
+ if(c > 0xffffffffL)
+ return -1;
+ if(c > 0xffff) {
+ BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+ if(!io_ch(arg, tmphex, 10)) return -1;
+ return 10;
+ }
+ if(c > 0xff) {
+ BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
+ if(!io_ch(arg, tmphex, 6)) return -1;
+ return 6;
+ }
+ chtmp = (unsigned char)c;
+ if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB;
+ else chflgs = char_type[chtmp] & flags;
+ if(chflgs & CHARTYPE_BS_ESC) {
+ /* If we don't escape with quotes, signal we need quotes */
+ if(chflgs & ASN1_STRFLGS_ESC_QUOTE) {
+ if(do_quotes) *do_quotes = 1;
+ if(!io_ch(arg, &chtmp, 1)) return -1;
+ return 1;
+ }
+ if(!io_ch(arg, "\\", 1)) return -1;
+ if(!io_ch(arg, &chtmp, 1)) return -1;
+ return 2;
+ }
+ if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
+ BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
+ if(!io_ch(arg, tmphex, 3)) return -1;
+ return 3;
+ }
+ /* If we get this far and do any escaping at all must escape
+ * the escape character itself: backslash.
+ */
+ if (chtmp == '\\' && flags & ESC_FLAGS) {
+ if(!io_ch(arg, "\\\\", 2)) return -1;
+ return 2;
+ }
+ if(!io_ch(arg, &chtmp, 1)) return -1;
+ return 1;
+}
+
+#define BUF_TYPE_WIDTH_MASK 0x7
+#define BUF_TYPE_CONVUTF8 0x8
+
+/* This function sends each character in a buffer to
+ * do_esc_char(). It interprets the content formats
+ * and converts to or from UTF8 as appropriate.
+ */
+
+static int do_buf(unsigned char *buf, int buflen,
+ int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg)
+{
+ int i, outlen, len;
+ unsigned char orflags, *p, *q;
+ unsigned long c;
+ p = buf;
+ q = buf + buflen;
+ outlen = 0;
+ while(p != q) {
+ if(p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253;
+ else orflags = 0;
+ switch(type & BUF_TYPE_WIDTH_MASK) {
+ case 4:
+ c = ((unsigned long)*p++) << 24;
+ c |= ((unsigned long)*p++) << 16;
+ c |= ((unsigned long)*p++) << 8;
+ c |= *p++;
+ break;
+
+ case 2:
+ c = ((unsigned long)*p++) << 8;
+ c |= *p++;
+ break;
+
+ case 1:
+ c = *p++;
+ break;
+
+ case 0:
+ i = UTF8_getc(p, buflen, &c);
+ if(i < 0) return -1; /* Invalid UTF8String */
+ p += i;
+ break;
+ default:
+ return -1; /* invalid width */
+ }
+ if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253;
+ if(type & BUF_TYPE_CONVUTF8) {
+ unsigned char utfbuf[6];
+ int utflen;
+ utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
+ for(i = 0; i < utflen; i++) {
+ /* We don't need to worry about setting orflags correctly
+ * because if utflen==1 its value will be correct anyway
+ * otherwise each character will be > 0x7f and so the
+ * character will never be escaped on first and last.
+ */
+ len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg);
+ if(len < 0) return -1;
+ outlen += len;
+ }
+ } else {
+ len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg);
+ if(len < 0) return -1;
+ outlen += len;
+ }
+ }
+ return outlen;
+}
+
+/* This function hex dumps a buffer of characters */
+
+static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
+{
+ static const char hexdig[] = "0123456789ABCDEF";
+ unsigned char *p, *q;
+ char hextmp[2];
+ if(arg) {
+ p = buf;
+ q = buf + buflen;
+ while(p != q) {
+ hextmp[0] = hexdig[*p >> 4];
+ hextmp[1] = hexdig[*p & 0xf];
+ if(!io_ch(arg, hextmp, 2)) return -1;
+ p++;
+ }
+ }
+ return buflen << 1;
+}
+
+/* "dump" a string. This is done when the type is unknown,
+ * or the flags request it. We can either dump the content
+ * octets or the entire DER encoding. This uses the RFC2253
+ * #01234 format.
+ */
+
+static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
+{
+ /* Placing the ASN1_STRING in a temp ASN1_TYPE allows
+ * the DER encoding to readily obtained
+ */
+ ASN1_TYPE t;
+ unsigned char *der_buf, *p;
+ int outlen, der_len;
+
+ if(!io_ch(arg, "#", 1)) return -1;
+ /* If we don't dump DER encoding just dump content octets */
+ if(!(lflags & ASN1_STRFLGS_DUMP_DER)) {
+ outlen = do_hex_dump(io_ch, arg, str->data, str->length);
+ if(outlen < 0) return -1;
+ return outlen + 1;
+ }
+ t.type = str->type;
+ t.value.ptr = (char *)str;
+ der_len = i2d_ASN1_TYPE(&t, NULL);
+ der_buf = OPENSSL_malloc(der_len);
+ if(!der_buf) return -1;
+ p = der_buf;
+ i2d_ASN1_TYPE(&t, &p);
+ outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
+ OPENSSL_free(der_buf);
+ if(outlen < 0) return -1;
+ return outlen + 1;
+}
+
+/* Lookup table to convert tags to character widths,
+ * 0 = UTF8 encoded, -1 is used for non string types
+ * otherwise it is the number of bytes per character
+ */
+
+static const signed char tag2nbyte[] = {
+ -1, -1, -1, -1, -1, /* 0-4 */
+ -1, -1, -1, -1, -1, /* 5-9 */
+ -1, -1, 0, -1, /* 10-13 */
+ -1, -1, -1, -1, /* 15-17 */
+ -1, 1, 1, /* 18-20 */
+ -1, 1, 1, 1, /* 21-24 */
+ -1, 1, -1, /* 25-27 */
+ 4, -1, 2 /* 28-30 */
+};
+
+/* This is the main function, print out an
+ * ASN1_STRING taking note of various escape
+ * and display options. Returns number of
+ * characters written or -1 if an error
+ * occurred.
+ */
+
+static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str)
+{
+ int outlen, len;
+ int type;
+ char quotes;
+ unsigned char flags;
+ quotes = 0;
+ /* Keep a copy of escape flags */
+ flags = (unsigned char)(lflags & ESC_FLAGS);
+
+ type = str->type;
+
+ outlen = 0;
+
+
+ if(lflags & ASN1_STRFLGS_SHOW_TYPE) {
+ const char *tagname;
+ tagname = ASN1_tag2str(type);
+ outlen += strlen(tagname);
+ if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1;
+ outlen++;
+ }
+
+ /* Decide what to do with type, either dump content or display it */
+
+ /* Dump everything */
+ if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1;
+ /* Ignore the string type */
+ else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1;
+ else {
+ /* Else determine width based on type */
+ if((type > 0) && (type < 31)) type = tag2nbyte[type];
+ else type = -1;
+ if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1;
+ }
+
+ if(type == -1) {
+ len = do_dump(lflags, io_ch, arg, str);
+ if(len < 0) return -1;
+ outlen += len;
+ return outlen;
+ }
+
+ if(lflags & ASN1_STRFLGS_UTF8_CONVERT) {
+ /* Note: if string is UTF8 and we want
+ * to convert to UTF8 then we just interpret
+ * it as 1 byte per character to avoid converting
+ * twice.
+ */
+ if(!type) type = 1;
+ else type |= BUF_TYPE_CONVUTF8;
+ }
+
+ len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
+ if(len < 0) return -1;
+ outlen += len;
+ if(quotes) outlen += 2;
+ if(!arg) return outlen;
+ if(quotes && !io_ch(arg, "\"", 1)) return -1;
+ if(do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
+ return -1;
+ if(quotes && !io_ch(arg, "\"", 1)) return -1;
+ return outlen;
+}
+
+/* Used for line indenting: print 'indent' spaces */
+
+static int do_indent(char_io *io_ch, void *arg, int indent)
+{
+ int i;
+ for(i = 0; i < indent; i++)
+ if(!io_ch(arg, " ", 1)) return 0;
+ return 1;
+}
+
+#define FN_WIDTH_LN 25
+#define FN_WIDTH_SN 10
+
+static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
+ int indent, unsigned long flags)
+{
+ int i, prev = -1, orflags, cnt;
+ int fn_opt, fn_nid;
+ ASN1_OBJECT *fn;
+ ASN1_STRING *val;
+ X509_NAME_ENTRY *ent;
+ char objtmp[80];
+ const char *objbuf;
+ int outlen, len;
+ const char *sep_dn, *sep_mv, *sep_eq;
+ int sep_dn_len, sep_mv_len, sep_eq_len;
+ if(indent < 0) indent = 0;
+ outlen = indent;
+ if(!do_indent(io_ch, arg, indent)) return -1;
+ switch (flags & XN_FLAG_SEP_MASK)
+ {
+ case XN_FLAG_SEP_MULTILINE:
+ sep_dn = "\n";
+ sep_dn_len = 1;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ break;
+
+ case XN_FLAG_SEP_COMMA_PLUS:
+ sep_dn = ",";
+ sep_dn_len = 1;
+ sep_mv = "+";
+ sep_mv_len = 1;
+ indent = 0;
+ break;
+
+ case XN_FLAG_SEP_CPLUS_SPC:
+ sep_dn = ", ";
+ sep_dn_len = 2;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ indent = 0;
+ break;
+
+ case XN_FLAG_SEP_SPLUS_SPC:
+ sep_dn = "; ";
+ sep_dn_len = 2;
+ sep_mv = " + ";
+ sep_mv_len = 3;
+ indent = 0;
+ break;
+
+ default:
+ return -1;
+ }
+
+ if(flags & XN_FLAG_SPC_EQ) {
+ sep_eq = " = ";
+ sep_eq_len = 3;
+ } else {
+ sep_eq = "=";
+ sep_eq_len = 1;
+ }
+
+ fn_opt = flags & XN_FLAG_FN_MASK;
+
+ cnt = X509_NAME_entry_count(n);
+ for(i = 0; i < cnt; i++) {
+ if(flags & XN_FLAG_DN_REV)
+ ent = X509_NAME_get_entry(n, cnt - i - 1);
+ else ent = X509_NAME_get_entry(n, i);
+ if(prev != -1) {
+ if(prev == ent->set) {
+ if(!io_ch(arg, sep_mv, sep_mv_len)) return -1;
+ outlen += sep_mv_len;
+ } else {
+ if(!io_ch(arg, sep_dn, sep_dn_len)) return -1;
+ outlen += sep_dn_len;
+ if(!do_indent(io_ch, arg, indent)) return -1;
+ outlen += indent;
+ }
+ }
+ prev = ent->set;
+ fn = X509_NAME_ENTRY_get_object(ent);
+ val = X509_NAME_ENTRY_get_data(ent);
+ fn_nid = OBJ_obj2nid(fn);
+ if(fn_opt != XN_FLAG_FN_NONE) {
+ int objlen, fld_len;
+ if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) {
+ OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+ fld_len = 0; /* XXX: what should this be? */
+ objbuf = objtmp;
+ } else {
+ if(fn_opt == XN_FLAG_FN_SN) {
+ fld_len = FN_WIDTH_SN;
+ objbuf = OBJ_nid2sn(fn_nid);
+ } else if(fn_opt == XN_FLAG_FN_LN) {
+ fld_len = FN_WIDTH_LN;
+ objbuf = OBJ_nid2ln(fn_nid);
+ } else {
+ fld_len = 0; /* XXX: what should this be? */
+ objbuf = "";
+ }
+ }
+ objlen = strlen(objbuf);
+ if(!io_ch(arg, objbuf, objlen)) return -1;
+ if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
+ if (!do_indent(io_ch, arg, fld_len - objlen)) return -1;
+ outlen += fld_len - objlen;
+ }
+ if(!io_ch(arg, sep_eq, sep_eq_len)) return -1;
+ outlen += objlen + sep_eq_len;
+ }
+ /* If the field name is unknown then fix up the DER dump
+ * flag. We might want to limit this further so it will
+ * DER dump on anything other than a few 'standard' fields.
+ */
+ if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
+ orflags = ASN1_STRFLGS_DUMP_ALL;
+ else orflags = 0;
+
+ len = do_print_ex(io_ch, arg, flags | orflags, val);
+ if(len < 0) return -1;
+ outlen += len;
+ }
+ return outlen;
+}
+
+/* Wrappers round the main functions */
+
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags)
+{
+ if(flags == XN_FLAG_COMPAT)
+ return X509_NAME_print(out, nm, indent);
+ return do_name_ex(send_bio_chars, out, nm, indent, flags);
+}
+
+#ifndef OPENSSL_NO_FP_API
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags)
+{
+ if(flags == XN_FLAG_COMPAT)
+ {
+ BIO *btmp;
+ int ret;
+ btmp = BIO_new_fp(fp, BIO_NOCLOSE);
+ if(!btmp) return -1;
+ ret = X509_NAME_print(btmp, nm, indent);
+ BIO_free(btmp);
+ return ret;
+ }
+ return do_name_ex(send_fp_chars, fp, nm, indent, flags);
+}
+#endif
+
+int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
+{
+ return do_print_ex(send_bio_chars, out, flags, str);
+}
+
+#ifndef OPENSSL_NO_FP_API
+int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
+{
+ return do_print_ex(send_fp_chars, fp, flags, str);
+}
+#endif
+
+/* Utility function: convert any string type to UTF8, returns number of bytes
+ * in output string or a negative error code
+ */
+
+int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
+{
+ ASN1_STRING stmp, *str = &stmp;
+ int mbflag, type, ret;
+ if(!in) return -1;
+ type = in->type;
+ if((type < 0) || (type > 30)) return -1;
+ mbflag = tag2nbyte[type];
+ if(mbflag == -1) return -1;
+ mbflag |= MBSTRING_FLAG;
+ stmp.data = NULL;
+ stmp.length = 0;
+ stmp.flags = 0;
+ ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
+ if(ret < 0) return ret;
+ *out = stmp.data;
+ return stmp.length;
+}
diff --git a/src/crypto/x509/a_verify.c b/src/crypto/x509/a_verify.c
new file mode 100644
index 0000000..72e0a62
--- /dev/null
+++ b/src/crypto/x509/a_verify.c
@@ -0,0 +1,133 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <stdio.h>
+#include <time.h>
+#include <sys/types.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+
+#include "../evp/internal.h"
+
+
+int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
+ ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+ {
+ EVP_MD_CTX ctx;
+ uint8_t *buf_in = NULL;
+ int ret = 0, inl;
+
+ if (!pkey)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_PASSED_NULL_PARAMETER);
+ return 0;
+ }
+
+ if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, X509_R_INVALID_BIT_STRING_BITS_LEFT);
+ return 0;
+ }
+
+ EVP_MD_CTX_init(&ctx);
+
+ if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
+ {
+ goto err;
+ }
+
+ inl = ASN1_item_i2d(asn, &buf_in, it);
+
+ if (buf_in == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
+ {
+ OPENSSL_cleanse(buf_in,(unsigned int)inl);
+ OPENSSL_free(buf_in);
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ OPENSSL_cleanse(buf_in,(unsigned int)inl);
+ OPENSSL_free(buf_in);
+
+ if (EVP_DigestVerifyFinal(&ctx,signature->data,
+ (size_t)signature->length) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_item_verify, ERR_R_EVP_LIB);
+ goto err;
+ }
+ /* we don't need to zero the 'ctx' because we just checked
+ * public information */
+ /* memset(&ctx,0,sizeof(ctx)); */
+ ret = 1;
+err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return ret;
+ }
+
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
new file mode 100644
index 0000000..750701e
--- /dev/null
+++ b/src/crypto/x509/asn1_gen.c
@@ -0,0 +1,862 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+#define ASN1_GEN_FLAG 0x10000
+#define ASN1_GEN_FLAG_IMP (ASN1_GEN_FLAG|1)
+#define ASN1_GEN_FLAG_EXP (ASN1_GEN_FLAG|2)
+#define ASN1_GEN_FLAG_TAG (ASN1_GEN_FLAG|3)
+#define ASN1_GEN_FLAG_BITWRAP (ASN1_GEN_FLAG|4)
+#define ASN1_GEN_FLAG_OCTWRAP (ASN1_GEN_FLAG|5)
+#define ASN1_GEN_FLAG_SEQWRAP (ASN1_GEN_FLAG|6)
+#define ASN1_GEN_FLAG_SETWRAP (ASN1_GEN_FLAG|7)
+#define ASN1_GEN_FLAG_FORMAT (ASN1_GEN_FLAG|8)
+
+#define ASN1_GEN_STR(str,val) {str, sizeof(str) - 1, val}
+
+#define ASN1_FLAG_EXP_MAX 20
+
+/* Input formats */
+
+/* ASCII: default */
+#define ASN1_GEN_FORMAT_ASCII 1
+/* UTF8 */
+#define ASN1_GEN_FORMAT_UTF8 2
+/* Hex */
+#define ASN1_GEN_FORMAT_HEX 3
+/* List of bits */
+#define ASN1_GEN_FORMAT_BITLIST 4
+
+
+struct tag_name_st
+ {
+ const char *strnam;
+ int len;
+ int tag;
+ };
+
+typedef struct
+ {
+ int exp_tag;
+ int exp_class;
+ int exp_constructed;
+ int exp_pad;
+ long exp_len;
+ } tag_exp_type;
+
+typedef struct
+ {
+ int imp_tag;
+ int imp_class;
+ int utype;
+ int format;
+ const char *str;
+ tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
+ int exp_count;
+ } tag_exp_arg;
+
+static int bitstr_cb(const char *elem, int len, void *bitstr);
+static int asn1_cb(const char *elem, int len, void *bitstr);
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok);
+static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass);
+static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
+static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
+static int asn1_str2tag(const char *tagstr, int len);
+
+ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
+ {
+ X509V3_CTX cnf;
+
+ if (!nconf)
+ return ASN1_generate_v3(str, NULL);
+
+ X509V3_set_nconf(&cnf, nconf);
+ return ASN1_generate_v3(str, &cnf);
+ }
+
+ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
+ {
+ ASN1_TYPE *ret;
+ tag_exp_arg asn1_tags;
+ tag_exp_type *etmp;
+
+ int i, len;
+
+ unsigned char *orig_der = NULL, *new_der = NULL;
+ const unsigned char *cpy_start;
+ unsigned char *p;
+ const unsigned char *cp;
+ int cpy_len;
+ long hdr_len;
+ int hdr_constructed = 0, hdr_tag, hdr_class;
+ int r;
+
+ asn1_tags.imp_tag = -1;
+ asn1_tags.imp_class = -1;
+ asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
+ asn1_tags.exp_count = 0;
+ if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
+ return NULL;
+
+ if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET))
+ {
+ if (!cnf)
+ {
+ OPENSSL_PUT_ERROR(X509, ASN1_generate_v3, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+ return NULL;
+ }
+ ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
+ }
+ else
+ ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
+
+ if (!ret)
+ return NULL;
+
+ /* If no tagging return base type */
+ if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
+ return ret;
+
+ /* Generate the encoding */
+ cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
+ ASN1_TYPE_free(ret);
+ ret = NULL;
+ /* Set point to start copying for modified encoding */
+ cpy_start = orig_der;
+
+ /* Do we need IMPLICIT tagging? */
+ if (asn1_tags.imp_tag != -1)
+ {
+ /* If IMPLICIT we will replace the underlying tag */
+ /* Skip existing tag+len */
+ r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len);
+ if (r & 0x80)
+ goto err;
+ /* Update copy length */
+ cpy_len -= cpy_start - orig_der;
+ /* For IMPLICIT tagging the length should match the
+ * original length and constructed flag should be
+ * consistent.
+ */
+ if (r & 0x1)
+ {
+ /* Indefinite length constructed */
+ hdr_constructed = 2;
+ hdr_len = 0;
+ }
+ else
+ /* Just retain constructed flag */
+ hdr_constructed = r & V_ASN1_CONSTRUCTED;
+ /* Work out new length with IMPLICIT tag: ignore constructed
+ * because it will mess up if indefinite length
+ */
+ len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
+ }
+ else
+ len = cpy_len;
+
+ /* Work out length in any EXPLICIT, starting from end */
+
+ for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--)
+ {
+ /* Content length: number of content octets + any padding */
+ len += etmp->exp_pad;
+ etmp->exp_len = len;
+ /* Total object length: length including new header */
+ len = ASN1_object_size(0, len, etmp->exp_tag);
+ }
+
+ /* Allocate buffer for new encoding */
+
+ new_der = OPENSSL_malloc(len);
+ if (!new_der)
+ goto err;
+
+ /* Generate tagged encoding */
+
+ p = new_der;
+
+ /* Output explicit tags first */
+
+ for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++)
+ {
+ ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
+ etmp->exp_tag, etmp->exp_class);
+ if (etmp->exp_pad)
+ *p++ = 0;
+ }
+
+ /* If IMPLICIT, output tag */
+
+ if (asn1_tags.imp_tag != -1)
+ {
+ if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
+ && (asn1_tags.imp_tag == V_ASN1_SEQUENCE
+ || asn1_tags.imp_tag == V_ASN1_SET) )
+ hdr_constructed = V_ASN1_CONSTRUCTED;
+ ASN1_put_object(&p, hdr_constructed, hdr_len,
+ asn1_tags.imp_tag, asn1_tags.imp_class);
+ }
+
+ /* Copy across original encoding */
+ memcpy(p, cpy_start, cpy_len);
+
+ cp = new_der;
+
+ /* Obtain new ASN1_TYPE structure */
+ ret = d2i_ASN1_TYPE(NULL, &cp, len);
+
+ err:
+ if (orig_der)
+ OPENSSL_free(orig_der);
+ if (new_der)
+ OPENSSL_free(new_der);
+
+ return ret;
+
+ }
+
+static int asn1_cb(const char *elem, int len, void *bitstr)
+ {
+ tag_exp_arg *arg = bitstr;
+ int i;
+ int utype;
+ int vlen = 0;
+ const char *p, *vstart = NULL;
+
+ int tmp_tag, tmp_class;
+
+ if (elem == NULL)
+ return 0;
+
+ for(i = 0, p = elem; i < len; p++, i++)
+ {
+ /* Look for the ':' in name value pairs */
+ if (*p == ':')
+ {
+ vstart = p + 1;
+ vlen = len - (vstart - elem);
+ len = p - elem;
+ break;
+ }
+ }
+
+ utype = asn1_str2tag(elem, len);
+
+ if (utype == -1)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_TAG);
+ ERR_add_error_data(2, "tag=", elem);
+ return -1;
+ }
+
+ /* If this is not a modifier mark end of string and exit */
+ if (!(utype & ASN1_GEN_FLAG))
+ {
+ arg->utype = utype;
+ arg->str = vstart;
+ /* If no value and not end of string, error */
+ if (!vstart && elem[len])
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_MISSING_VALUE);
+ return -1;
+ }
+ return 0;
+ }
+
+ switch(utype)
+ {
+
+ case ASN1_GEN_FLAG_IMP:
+ /* Check for illegal multiple IMPLICIT tagging */
+ if (arg->imp_tag != -1)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_ILLEGAL_NESTED_TAGGING);
+ return -1;
+ }
+ if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_EXP:
+
+ if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
+ return -1;
+ if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_SEQWRAP:
+ if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_SETWRAP:
+ if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_BITWRAP:
+ if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_OCTWRAP:
+ if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
+ return -1;
+ break;
+
+ case ASN1_GEN_FLAG_FORMAT:
+ if (!strncmp(vstart, "ASCII", 5))
+ arg->format = ASN1_GEN_FORMAT_ASCII;
+ else if (!strncmp(vstart, "UTF8", 4))
+ arg->format = ASN1_GEN_FORMAT_UTF8;
+ else if (!strncmp(vstart, "HEX", 3))
+ arg->format = ASN1_GEN_FORMAT_HEX;
+ else if (!strncmp(vstart, "BITLIST", 3))
+ arg->format = ASN1_GEN_FORMAT_BITLIST;
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_cb, ASN1_R_UNKNOWN_FORMAT);
+ return -1;
+ }
+ break;
+
+ }
+
+ return 1;
+
+ }
+
+static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
+ {
+ char erch[2];
+ long tag_num;
+ char *eptr;
+ if (!vstart)
+ return 0;
+ tag_num = strtoul(vstart, &eptr, 10);
+ /* Check we haven't gone past max length: should be impossible */
+ if (eptr && *eptr && (eptr > vstart + vlen))
+ return 0;
+ if (tag_num < 0)
+ {
+ OPENSSL_PUT_ERROR(X509, parse_tagging, ASN1_R_INVALID_NUMBER);
+ return 0;
+ }
+ *ptag = tag_num;
+ /* If we have non numeric characters, parse them */
+ if (eptr)
+ vlen -= eptr - vstart;
+ else
+ vlen = 0;
+ if (vlen)
+ {
+ switch (*eptr)
+ {
+
+ case 'U':
+ *pclass = V_ASN1_UNIVERSAL;
+ break;
+
+ case 'A':
+ *pclass = V_ASN1_APPLICATION;
+ break;
+
+ case 'P':
+ *pclass = V_ASN1_PRIVATE;
+ break;
+
+ case 'C':
+ *pclass = V_ASN1_CONTEXT_SPECIFIC;
+ break;
+
+ default:
+ erch[0] = *eptr;
+ erch[1] = 0;
+ OPENSSL_PUT_ERROR(X509, parse_tagging, ASN1_R_INVALID_MODIFIER);
+ ERR_add_error_data(2, "Char=", erch);
+ return 0;
+ break;
+
+ }
+ }
+ else
+ *pclass = V_ASN1_CONTEXT_SPECIFIC;
+
+ return 1;
+
+ }
+
+/* Handle multiple types: SET and SEQUENCE */
+
+static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
+ {
+ ASN1_TYPE *ret = NULL;
+ STACK_OF(ASN1_TYPE) *sk = NULL;
+ STACK_OF(CONF_VALUE) *sect = NULL;
+ unsigned char *der = NULL;
+ int derlen;
+ size_t i;
+ sk = sk_ASN1_TYPE_new_null();
+ if (!sk)
+ goto bad;
+ if (section)
+ {
+ if (!cnf)
+ goto bad;
+ sect = X509V3_get_section(cnf, (char *)section);
+ if (!sect)
+ goto bad;
+ for (i = 0; i < sk_CONF_VALUE_num(sect); i++)
+ {
+ ASN1_TYPE *typ = ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
+ if (!typ)
+ goto bad;
+ if (!sk_ASN1_TYPE_push(sk, typ))
+ goto bad;
+ }
+ }
+
+ /* Now we has a STACK of the components, convert to the correct form */
+
+ if (utype == V_ASN1_SET)
+ derlen = i2d_ASN1_SET_ANY(sk, &der);
+ else
+ derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
+
+ if (derlen < 0)
+ goto bad;
+
+ if (!(ret = ASN1_TYPE_new()))
+ goto bad;
+
+ if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
+ goto bad;
+
+ ret->type = utype;
+
+ ret->value.asn1_string->data = der;
+ ret->value.asn1_string->length = derlen;
+
+ der = NULL;
+
+ bad:
+
+ if (der)
+ OPENSSL_free(der);
+
+ if (sk)
+ sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+ if (sect)
+ X509V3_section_free(cnf, sect);
+
+ return ret;
+ }
+
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok)
+ {
+ tag_exp_type *exp_tmp;
+ /* Can only have IMPLICIT if permitted */
+ if ((arg->imp_tag != -1) && !imp_ok)
+ {
+ OPENSSL_PUT_ERROR(X509, append_exp, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+ return 0;
+ }
+
+ if (arg->exp_count == ASN1_FLAG_EXP_MAX)
+ {
+ OPENSSL_PUT_ERROR(X509, append_exp, ASN1_R_DEPTH_EXCEEDED);
+ return 0;
+ }
+
+ exp_tmp = &arg->exp_list[arg->exp_count++];
+
+ /* If IMPLICIT set tag to implicit value then
+ * reset implicit tag since it has been used.
+ */
+ if (arg->imp_tag != -1)
+ {
+ exp_tmp->exp_tag = arg->imp_tag;
+ exp_tmp->exp_class = arg->imp_class;
+ arg->imp_tag = -1;
+ arg->imp_class = -1;
+ }
+ else
+ {
+ exp_tmp->exp_tag = exp_tag;
+ exp_tmp->exp_class = exp_class;
+ }
+ exp_tmp->exp_constructed = exp_constructed;
+ exp_tmp->exp_pad = exp_pad;
+
+ return 1;
+ }
+
+
+static int asn1_str2tag(const char *tagstr, int len)
+ {
+ unsigned int i;
+ static const struct tag_name_st *tntmp, tnst [] = {
+ ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
+ ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
+ ASN1_GEN_STR("NULL", V_ASN1_NULL),
+ ASN1_GEN_STR("INT", V_ASN1_INTEGER),
+ ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
+ ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
+ ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
+ ASN1_GEN_STR("OID", V_ASN1_OBJECT),
+ ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
+ ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
+ ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
+ ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
+ ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
+ ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
+ ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
+ ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
+ ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
+ ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
+ ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
+ ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
+ ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
+ ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
+ ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
+ ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
+ ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
+ ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
+ ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
+ ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
+ ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
+ ASN1_GEN_STR("T61", V_ASN1_T61STRING),
+ ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
+ ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
+ ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
+ ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
+ ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
+ ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
+
+ /* Special cases */
+ ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
+ ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
+ ASN1_GEN_STR("SET", V_ASN1_SET),
+ /* type modifiers */
+ /* Explicit tag */
+ ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
+ ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
+ /* Implicit tag */
+ ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
+ ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
+ /* OCTET STRING wrapper */
+ ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
+ /* SEQUENCE wrapper */
+ ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
+ /* SET wrapper */
+ ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
+ /* BIT STRING wrapper */
+ ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
+ ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
+ ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
+ };
+
+ if (len == -1)
+ len = strlen(tagstr);
+
+ tntmp = tnst;
+ for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++)
+ {
+ if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
+ return tntmp->tag;
+ }
+
+ return -1;
+ }
+
+static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
+ {
+ ASN1_TYPE *atmp = NULL;
+
+ CONF_VALUE vtmp;
+
+ unsigned char *rdata;
+ long rdlen;
+
+ int no_unused = 1;
+
+ if (!(atmp = ASN1_TYPE_new()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+
+ if (!str)
+ str = "";
+
+ switch(utype)
+ {
+
+ case V_ASN1_NULL:
+ if (str && *str)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_NULL_VALUE);
+ goto bad_form;
+ }
+ break;
+
+ case V_ASN1_BOOLEAN:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ vtmp.name = NULL;
+ vtmp.section = NULL;
+ vtmp.value = (char *)str;
+ if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BOOLEAN);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_INTEGER:
+ case V_ASN1_ENUMERATED:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_INTEGER);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_OBJECT:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_OBJECT);
+ goto bad_str;
+ }
+ break;
+
+ case V_ASN1_UTCTIME:
+ case V_ASN1_GENERALIZEDTIME:
+ if (format != ASN1_GEN_FORMAT_ASCII)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_TIME_NOT_ASCII_FORMAT);
+ goto bad_form;
+ }
+ if (!(atmp->value.asn1_string = ASN1_STRING_new()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+ atmp->value.asn1_string->type = utype;
+ if (!ASN1_TIME_check(atmp->value.asn1_string))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_TIME_VALUE);
+ goto bad_str;
+ }
+
+ break;
+
+ case V_ASN1_BMPSTRING:
+ case V_ASN1_PRINTABLESTRING:
+ case V_ASN1_IA5STRING:
+ case V_ASN1_T61STRING:
+ case V_ASN1_UTF8STRING:
+ case V_ASN1_VISIBLESTRING:
+ case V_ASN1_UNIVERSALSTRING:
+ case V_ASN1_GENERALSTRING:
+ case V_ASN1_NUMERICSTRING:
+
+ if (format == ASN1_GEN_FORMAT_ASCII)
+ format = MBSTRING_ASC;
+ else if (format == ASN1_GEN_FORMAT_UTF8)
+ format = MBSTRING_UTF8;
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_FORMAT);
+ goto bad_form;
+ }
+
+
+ if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
+ -1, format, ASN1_tag2bit(utype)) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_str;
+ }
+
+
+ break;
+
+ case V_ASN1_BIT_STRING:
+
+ case V_ASN1_OCTET_STRING:
+
+ if (!(atmp->value.asn1_string = ASN1_STRING_new()))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ERR_R_MALLOC_FAILURE);
+ goto bad_form;
+ }
+
+ if (format == ASN1_GEN_FORMAT_HEX)
+ {
+
+ if (!(rdata = string_to_hex((char *)str, &rdlen)))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_HEX);
+ goto bad_str;
+ }
+
+ atmp->value.asn1_string->data = rdata;
+ atmp->value.asn1_string->length = rdlen;
+ atmp->value.asn1_string->type = utype;
+
+ }
+ else if (format == ASN1_GEN_FORMAT_ASCII)
+ ASN1_STRING_set(atmp->value.asn1_string, str, -1);
+ else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING))
+ {
+ if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_LIST_ERROR);
+ goto bad_str;
+ }
+ no_unused = 0;
+
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+ goto bad_form;
+ }
+
+ if ((utype == V_ASN1_BIT_STRING) && no_unused)
+ {
+ atmp->value.asn1_string->flags
+ &= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ atmp->value.asn1_string->flags
+ |= ASN1_STRING_FLAG_BITS_LEFT;
+ }
+
+
+ break;
+
+ default:
+ OPENSSL_PUT_ERROR(X509, asn1_str2type, ASN1_R_UNSUPPORTED_TYPE);
+ goto bad_str;
+ break;
+ }
+
+
+ atmp->type = utype;
+ return atmp;
+
+
+ bad_str:
+ ERR_add_error_data(2, "string=", str);
+ bad_form:
+
+ ASN1_TYPE_free(atmp);
+ return NULL;
+
+ }
+
+static int bitstr_cb(const char *elem, int len, void *bitstr)
+ {
+ long bitnum;
+ char *eptr;
+ if (!elem)
+ return 0;
+ bitnum = strtoul(elem, &eptr, 10);
+ if (eptr && *eptr && (eptr != elem + len))
+ return 0;
+ if (bitnum < 0)
+ {
+ OPENSSL_PUT_ERROR(X509, bitstr_cb, ASN1_R_INVALID_NUMBER);
+ return 0;
+ }
+ if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
+ {
+ OPENSSL_PUT_ERROR(X509, bitstr_cb, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ return 1;
+ }
+
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
new file mode 100644
index 0000000..5a77b81
--- /dev/null
+++ b/src/crypto/x509/by_dir.c
@@ -0,0 +1,479 @@
+/* crypto/x509/by_dir.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+
+typedef struct lookup_dir_hashes_st
+ {
+ unsigned long hash;
+ int suffix;
+ } BY_DIR_HASH;
+
+typedef struct lookup_dir_entry_st
+ {
+ char *dir;
+ int dir_type;
+ STACK_OF(BY_DIR_HASH) *hashes;
+ } BY_DIR_ENTRY;
+
+typedef struct lookup_dir_st
+ {
+ BUF_MEM *buffer;
+ STACK_OF(BY_DIR_ENTRY) *dirs;
+ } BY_DIR;
+
+DECLARE_STACK_OF(BY_DIR_HASH)
+DECLARE_STACK_OF(BY_DIR_ENTRY)
+
+static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
+ char **ret);
+static int new_dir(X509_LOOKUP *lu);
+static void free_dir(X509_LOOKUP *lu);
+static int add_cert_dir(BY_DIR *ctx,const char *dir,int type);
+static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name,
+ X509_OBJECT *ret);
+X509_LOOKUP_METHOD x509_dir_lookup=
+ {
+ "Load certs from files in a directory",
+ new_dir, /* new */
+ free_dir, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ dir_ctrl, /* ctrl */
+ get_cert_by_subject, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ };
+
+X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
+ {
+ return(&x509_dir_lookup);
+ }
+
+static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
+ char **retp)
+ {
+ int ret=0;
+ BY_DIR *ld;
+ char *dir = NULL;
+
+ ld=(BY_DIR *)ctx->method_data;
+
+ switch (cmd)
+ {
+ case X509_L_ADD_DIR:
+ if (argl == X509_FILETYPE_DEFAULT)
+ {
+ dir=(char *)getenv(X509_get_default_cert_dir_env());
+ if (dir)
+ ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
+ else
+ ret=add_cert_dir(ld,X509_get_default_cert_dir(),
+ X509_FILETYPE_PEM);
+ if (!ret)
+ {
+ OPENSSL_PUT_ERROR(X509, dir_ctrl, X509_R_LOADING_CERT_DIR);
+ }
+ }
+ else
+ ret=add_cert_dir(ld,argp,(int)argl);
+ break;
+ }
+ return(ret);
+ }
+
+static int new_dir(X509_LOOKUP *lu)
+ {
+ BY_DIR *a;
+
+ if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
+ return(0);
+ if ((a->buffer=BUF_MEM_new()) == NULL)
+ {
+ OPENSSL_free(a);
+ return(0);
+ }
+ a->dirs=NULL;
+ lu->method_data=(char *)a;
+ return(1);
+ }
+
+static void by_dir_hash_free(BY_DIR_HASH *hash)
+ {
+ OPENSSL_free(hash);
+ }
+
+static int by_dir_hash_cmp(const BY_DIR_HASH **a,
+ const BY_DIR_HASH **b)
+ {
+ if ((*a)->hash > (*b)->hash)
+ return 1;
+ if ((*a)->hash < (*b)->hash)
+ return -1;
+ return 0;
+ }
+
+static void by_dir_entry_free(BY_DIR_ENTRY *ent)
+ {
+ if (ent->dir)
+ OPENSSL_free(ent->dir);
+ if (ent->hashes)
+ sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
+ OPENSSL_free(ent);
+ }
+
+static void free_dir(X509_LOOKUP *lu)
+ {
+ BY_DIR *a;
+
+ a=(BY_DIR *)lu->method_data;
+ if (a->dirs != NULL)
+ sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
+ if (a->buffer != NULL)
+ BUF_MEM_free(a->buffer);
+ OPENSSL_free(a);
+ }
+
+static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
+ {
+ size_t j,len;
+ const char *s,*ss,*p;
+
+ if (dir == NULL || !*dir)
+ {
+ OPENSSL_PUT_ERROR(X509, add_cert_dir, X509_R_INVALID_DIRECTORY);
+ return 0;
+ }
+
+ s=dir;
+ p=s;
+ do
+ {
+ if ((*p == ':') || (*p == '\0'))
+ {
+ BY_DIR_ENTRY *ent;
+ ss=s;
+ s=p+1;
+ len=p-ss;
+ if (len == 0) continue;
+ for (j=0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++)
+ {
+ ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
+ if (strlen(ent->dir) == len &&
+ strncmp(ent->dir,ss,len) == 0)
+ break;
+ }
+ if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
+ continue;
+ if (ctx->dirs == NULL)
+ {
+ ctx->dirs = sk_BY_DIR_ENTRY_new_null();
+ if (!ctx->dirs)
+ {
+ OPENSSL_PUT_ERROR(X509, add_cert_dir, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ }
+ ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
+ if (!ent)
+ return 0;
+ ent->dir_type = type;
+ ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
+ ent->dir = OPENSSL_malloc(len+1);
+ if (!ent->dir || !ent->hashes)
+ {
+ by_dir_entry_free(ent);
+ return 0;
+ }
+ strncpy(ent->dir,ss,len);
+ ent->dir[len] = '\0';
+ if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
+ {
+ by_dir_entry_free(ent);
+ return 0;
+ }
+ }
+ } while (*p++ != '\0');
+ return 1;
+ }
+
+static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
+ X509_OBJECT *ret)
+ {
+ BY_DIR *ctx;
+ union {
+ struct {
+ X509 st_x509;
+ X509_CINF st_x509_cinf;
+ } x509;
+ struct {
+ X509_CRL st_crl;
+ X509_CRL_INFO st_crl_info;
+ } crl;
+ } data;
+ int ok=0;
+ size_t i;
+ int j,k;
+ unsigned long h;
+ unsigned long hash_array[2];
+ int hash_index;
+ BUF_MEM *b=NULL;
+ X509_OBJECT stmp,*tmp;
+ const char *postfix="";
+
+ if (name == NULL) return(0);
+
+ stmp.type=type;
+ if (type == X509_LU_X509)
+ {
+ data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
+ data.x509.st_x509_cinf.subject=name;
+ stmp.data.x509= &data.x509.st_x509;
+ postfix="";
+ }
+ else if (type == X509_LU_CRL)
+ {
+ data.crl.st_crl.crl= &data.crl.st_crl_info;
+ data.crl.st_crl_info.issuer=name;
+ stmp.data.crl= &data.crl.st_crl;
+ postfix="r";
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, X509_R_WRONG_LOOKUP_TYPE);
+ goto finish;
+ }
+
+ if ((b=BUF_MEM_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_BUF_LIB);
+ goto finish;
+ }
+
+ ctx=(BY_DIR *)xl->method_data;
+
+ hash_array[0]=X509_NAME_hash(name);
+ hash_array[1]=X509_NAME_hash_old(name);
+ for (hash_index=0; hash_index < 2; ++hash_index)
+ {
+ h=hash_array[hash_index];
+ for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
+ {
+ BY_DIR_ENTRY *ent;
+ size_t idx;
+ BY_DIR_HASH htmp, *hent;
+ ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
+ j=strlen(ent->dir)+1+8+6+1+1;
+ if (!BUF_MEM_grow(b,j))
+ {
+ OPENSSL_PUT_ERROR(X509, get_cert_by_subject, ERR_R_MALLOC_FAILURE);
+ goto finish;
+ }
+ if (type == X509_LU_CRL && ent->hashes)
+ {
+ htmp.hash = h;
+ CRYPTO_r_lock(CRYPTO_LOCK_X509_STORE);
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+ {
+ hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+ k = hent->suffix;
+ }
+ else
+ {
+ hent = NULL;
+ k=0;
+ }
+ CRYPTO_r_unlock(CRYPTO_LOCK_X509_STORE);
+ }
+ else
+ {
+ k = 0;
+ hent = NULL;
+ }
+ for (;;)
+ {
+ char c = '/';
+#ifdef OPENSSL_SYS_VMS
+ c = ent->dir[strlen(ent->dir)-1];
+ if (c != ':' && c != '>' && c != ']')
+ {
+ /* If no separator is present, we assume the
+ directory specifier is a logical name, and
+ add a colon. We really should use better
+ VMS routines for merging things like this,
+ but this will do for now...
+ -- Richard Levitte */
+ c = ':';
+ }
+ else
+ {
+ c = '\0';
+ }
+#endif
+ if (c == '\0')
+ {
+ /* This is special. When c == '\0', no
+ directory separator should be added. */
+ BIO_snprintf(b->data,b->max,
+ "%s%08lx.%s%d",ent->dir,h,
+ postfix,k);
+ }
+ else
+ {
+ BIO_snprintf(b->data,b->max,
+ "%s%c%08lx.%s%d",ent->dir,c,h,
+ postfix,k);
+ }
+#ifndef OPENSSL_NO_POSIX_IO
+#ifdef _WIN32
+#define stat _stat
+#endif
+ {
+ struct stat st;
+ if (stat(b->data,&st) < 0)
+ break;
+ }
+#endif
+ /* found one. */
+ if (type == X509_LU_X509)
+ {
+ if ((X509_load_cert_file(xl,b->data,
+ ent->dir_type)) == 0)
+ break;
+ }
+ else if (type == X509_LU_CRL)
+ {
+ if ((X509_load_crl_file(xl,b->data,
+ ent->dir_type)) == 0)
+ break;
+ }
+ /* else case will caught higher up */
+ k++;
+ }
+
+ /* we have added it to the cache so now pull
+ * it out again */
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ tmp = NULL;
+ if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
+ tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx);
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+
+ /* If a CRL, update the last file suffix added for this */
+
+ if (type == X509_LU_CRL)
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ /* Look for entry again in case another thread added
+ * an entry first.
+ */
+ if (!hent)
+ {
+ htmp.hash = h;
+ if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+ hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+ }
+ if (!hent)
+ {
+ hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+ hent->hash = h;
+ hent->suffix = k;
+ if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ OPENSSL_free(hent);
+ ok = 0;
+ goto finish;
+ }
+ }
+ else if (hent->suffix < k)
+ hent->suffix = k;
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ }
+
+ if (tmp != NULL)
+ {
+ ok=1;
+ ret->type=tmp->type;
+ memcpy(&ret->data,&tmp->data,sizeof(ret->data));
+ /* If we were going to up the reference count,
+ * we would need to do it on a perl 'type'
+ * basis */
+ /* CRYPTO_add(&tmp->data.x509->references,1,
+ CRYPTO_LOCK_X509);*/
+ goto finish;
+ }
+ }
+ }
+finish:
+ if (b != NULL) BUF_MEM_free(b);
+ return(ok);
+ }
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
new file mode 100644
index 0000000..2649631
--- /dev/null
+++ b/src/crypto/x509/by_file.c
@@ -0,0 +1,292 @@
+/* crypto/x509/by_file.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+#ifndef OPENSSL_NO_STDIO
+
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
+ long argl, char **ret);
+X509_LOOKUP_METHOD x509_file_lookup=
+ {
+ "Load file into cache",
+ NULL, /* new */
+ NULL, /* free */
+ NULL, /* init */
+ NULL, /* shutdown */
+ by_file_ctrl, /* ctrl */
+ NULL, /* get_by_subject */
+ NULL, /* get_by_issuer_serial */
+ NULL, /* get_by_fingerprint */
+ NULL, /* get_by_alias */
+ };
+
+X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
+ {
+ return(&x509_file_lookup);
+ }
+
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
+ char **ret)
+ {
+ int ok=0;
+ char *file;
+
+ switch (cmd)
+ {
+ case X509_L_FILE_LOAD:
+ if (argl == X509_FILETYPE_DEFAULT)
+ {
+ file = (char *)getenv(X509_get_default_cert_file_env());
+ if (file)
+ ok = (X509_load_cert_crl_file(ctx,file,
+ X509_FILETYPE_PEM) != 0);
+
+ else
+ ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
+ X509_FILETYPE_PEM) != 0);
+
+ if (!ok)
+ {
+ OPENSSL_PUT_ERROR(X509, by_file_ctrl, X509_R_LOADING_DEFAULTS);
+ }
+ }
+ else
+ {
+ if(argl == X509_FILETYPE_PEM)
+ ok = (X509_load_cert_crl_file(ctx,argp,
+ X509_FILETYPE_PEM) != 0);
+ else
+ ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0);
+ }
+ break;
+ }
+ return(ok);
+ }
+
+int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
+ {
+ int ret=0;
+ BIO *in=NULL;
+ int i,count=0;
+ X509 *x=NULL;
+
+ if (file == NULL) return(1);
+ in=BIO_new(BIO_s_file());
+
+ if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ if (type == X509_FILETYPE_PEM)
+ {
+ for (;;)
+ {
+ x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL);
+ if (x == NULL)
+ {
+ if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+ PEM_R_NO_START_LINE) && (count > 0))
+ {
+ ERR_clear_error();
+ break;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, ERR_R_PEM_LIB);
+ goto err;
+ }
+ }
+ i=X509_STORE_add_cert(ctx->store_ctx,x);
+ if (!i) goto err;
+ count++;
+ X509_free(x);
+ x=NULL;
+ }
+ ret=count;
+ }
+ else if (type == X509_FILETYPE_ASN1)
+ {
+ x=d2i_X509_bio(in,NULL);
+ if (x == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i=X509_STORE_add_cert(ctx->store_ctx,x);
+ if (!i) goto err;
+ ret=i;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_file, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+err:
+ if (x != NULL) X509_free(x);
+ if (in != NULL) BIO_free(in);
+ return(ret);
+ }
+
+int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+ {
+ int ret=0;
+ BIO *in=NULL;
+ int i,count=0;
+ X509_CRL *x=NULL;
+
+ if (file == NULL) return(1);
+ in=BIO_new(BIO_s_file());
+
+ if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, ERR_R_SYS_LIB);
+ goto err;
+ }
+
+ if (type == X509_FILETYPE_PEM)
+ {
+ for (;;)
+ {
+ x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
+ if (x == NULL)
+ {
+ if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+ PEM_R_NO_START_LINE) && (count > 0))
+ {
+ ERR_clear_error();
+ break;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, ERR_R_PEM_LIB);
+ goto err;
+ }
+ }
+ i=X509_STORE_add_crl(ctx->store_ctx,x);
+ if (!i) goto err;
+ count++;
+ X509_CRL_free(x);
+ x=NULL;
+ }
+ ret=count;
+ }
+ else if (type == X509_FILETYPE_ASN1)
+ {
+ x=d2i_X509_CRL_bio(in,NULL);
+ if (x == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, ERR_R_ASN1_LIB);
+ goto err;
+ }
+ i=X509_STORE_add_crl(ctx->store_ctx,x);
+ if (!i) goto err;
+ ret=i;
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_load_crl_file, X509_R_BAD_X509_FILETYPE);
+ goto err;
+ }
+err:
+ if (x != NULL) X509_CRL_free(x);
+ if (in != NULL) BIO_free(in);
+ return(ret);
+ }
+
+int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
+{
+ STACK_OF(X509_INFO) *inf;
+ X509_INFO *itmp;
+ BIO *in;
+ size_t i;
+ int count = 0;
+ if(type != X509_FILETYPE_PEM)
+ return X509_load_cert_file(ctx, file, type);
+ in = BIO_new_file(file, "r");
+ if(!in) {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_crl_file, ERR_R_SYS_LIB);
+ return 0;
+ }
+ inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+ BIO_free(in);
+ if(!inf) {
+ OPENSSL_PUT_ERROR(X509, X509_load_cert_crl_file, ERR_R_PEM_LIB);
+ return 0;
+ }
+ for(i = 0; i < sk_X509_INFO_num(inf); i++) {
+ itmp = sk_X509_INFO_value(inf, i);
+ if(itmp->x509) {
+ X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
+ count++;
+ }
+ if(itmp->crl) {
+ X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
+ count++;
+ }
+ }
+ sk_X509_INFO_pop_free(inf, X509_INFO_free);
+ return count;
+}
+
+#endif /* OPENSSL_NO_STDIO */
diff --git a/src/crypto/x509/charmap.h b/src/crypto/x509/charmap.h
new file mode 100644
index 0000000..b55e638
--- /dev/null
+++ b/src/crypto/x509/charmap.h
@@ -0,0 +1,15 @@
+/* Auto generated with chartype.pl script.
+ * Mask of various character properties
+ */
+
+static const unsigned char char_type[] = {
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+120, 0, 1,40, 0, 0, 0,16,16,16, 0,25,25,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16, 9, 9,16, 9,16,
+ 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16, 0, 1, 0, 0, 0,
+ 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
+16,16,16,16,16,16,16,16,16,16,16, 0, 0, 0, 0, 2
+};
+
diff --git a/src/crypto/x509/i2d_pr.c b/src/crypto/x509/i2d_pr.c
new file mode 100644
index 0000000..8896565
--- /dev/null
+++ b/src/crypto/x509/i2d_pr.c
@@ -0,0 +1,83 @@
+/* crypto/asn1/i2d_pr.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <stdio.h>
+
+#include <openssl/err.h>
+#include <openssl/evp.h>
+
+#include "../evp/internal.h"
+
+
+int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
+ {
+ if (a->ameth && a->ameth->old_priv_encode)
+ {
+ return a->ameth->old_priv_encode(a, pp);
+ }
+ if (a->ameth && a->ameth->priv_encode) {
+ PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8((EVP_PKEY*)a);
+ int ret = i2d_PKCS8_PRIV_KEY_INFO(p8,pp);
+ PKCS8_PRIV_KEY_INFO_free(p8);
+ return ret;
+ }
+ OPENSSL_PUT_ERROR(X509, i2d_PrivateKey, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+ return -1;
+ }
+
diff --git a/src/crypto/x509/pkcs7.c b/src/crypto/x509/pkcs7.c
new file mode 100644
index 0000000..75c101b
--- /dev/null
+++ b/src/crypto/x509/pkcs7.c
@@ -0,0 +1,154 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/x509.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+
+#include "../bytestring/internal.h"
+
+
+int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) {
+ uint8_t *der_bytes = NULL;
+ size_t der_len;
+ CBS in, content_info, content_type, wrapped_signed_data, signed_data,
+ certificates;
+ const size_t initial_certs_len = sk_X509_num(out_certs);
+ uint64_t version;
+ int ret = 0;
+
+ /* The input may be in BER format. */
+ if (!CBS_asn1_ber_to_der(cbs, &der_bytes, &der_len)) {
+ return 0;
+ }
+ if (der_bytes != NULL) {
+ CBS_init(&in, der_bytes, der_len);
+ } else {
+ CBS_init(&in, CBS_data(cbs), CBS_len(cbs));
+ }
+
+ /* See https://tools.ietf.org/html/rfc2315#section-7 */
+ if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) {
+ goto err;
+ }
+
+ if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_NOT_PKCS7_SIGNED_DATA);
+ goto err;
+ }
+
+ /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
+ if (!CBS_get_asn1(&content_info, &wrapped_signed_data,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) ||
+ !CBS_get_asn1_uint64(&signed_data, &version) ||
+ !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) ||
+ !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) {
+ goto err;
+ }
+
+ if (version < 1) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_BAD_PKCS7_VERSION);
+ goto err;
+ }
+
+ if (!CBS_get_asn1(&signed_data, &certificates,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates,
+ X509_R_NO_CERTIFICATES_INCLUDED);
+ goto err;
+ }
+
+ while (CBS_len(&certificates) > 0) {
+ CBS cert;
+ X509 *x509;
+ const uint8_t *inp;
+
+ if (!CBS_get_asn1_element(&certificates, &cert, CBS_ASN1_SEQUENCE)) {
+ goto err;
+ }
+
+ inp = CBS_data(&cert);
+ x509 = d2i_X509(NULL, &inp, CBS_len(&cert));
+ if (!x509) {
+ goto err;
+ }
+
+ if (inp != CBS_data(&cert) + CBS_len(&cert)) {
+ /* This suggests a disconnect between the two ASN.1 parsers. */
+ goto err;
+ }
+
+ sk_X509_push(out_certs, x509);
+ }
+
+ ret = 1;
+
+err:
+ if (der_bytes) {
+ OPENSSL_free(der_bytes);
+ }
+
+ if (!ret) {
+ while (sk_X509_num(out_certs) != initial_certs_len) {
+ X509 *x509 = sk_X509_pop(out_certs);
+ X509_free(x509);
+ }
+ }
+
+ return ret;
+}
+
+int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) {
+ CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
+ content_info, certificates;
+ size_t i;
+
+ /* See https://tools.ietf.org/html/rfc2315#section-7 */
+ if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
+ !CBB_add_asn1(&outer_seq, &wrapped_seq,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+ /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
+ !CBB_add_asn1(&wrapped_seq, &seq, CBS_ASN1_SEQUENCE) ||
+ !CBB_add_asn1(&seq, &version_bytes, CBS_ASN1_INTEGER) ||
+ !CBB_add_u8(&version_bytes, 1) ||
+ !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
+ !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
+ !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
+ !CBB_add_asn1(&seq, &certificates,
+ CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+ return 0;
+ }
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *x509 = sk_X509_value(certs, i);
+ uint8_t *buf;
+ int len = i2d_X509(x509, NULL);
+
+ if (len < 0 ||
+ !CBB_add_space(&certificates, &buf, len) ||
+ i2d_X509(x509, &buf) < 0) {
+ return 0;
+ }
+ }
+
+ return CBB_flush(out);
+}
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
new file mode 100644
index 0000000..4283022
--- /dev/null
+++ b/src/crypto/x509/pkcs7_test.c
@@ -0,0 +1,409 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+/* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
+ * using the Chrome UI. */
+static const uint8_t kPKCS7NSS[] = {
+ 0x30, 0x80, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+ 0x02, 0xa0, 0x80, 0x30, 0x80, 0x02, 0x01, 0x01, 0x31, 0x00, 0x30, 0x80,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0x00,
+ 0x00, 0xa0, 0x82, 0x0b, 0x1e, 0x30, 0x82, 0x03, 0x54, 0x30, 0x82, 0x02,
+ 0x3c, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x34, 0x56, 0x30,
+ 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+ 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04,
+ 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06, 0x03, 0x55,
+ 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
+ 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55,
+ 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75, 0x73, 0x74,
+ 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41, 0x30, 0x1e,
+ 0x17, 0x0d, 0x30, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30,
+ 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x35, 0x32, 0x31, 0x30,
+ 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09,
+ 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30,
+ 0x14, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54,
+ 0x72, 0x75, 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30,
+ 0x19, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54,
+ 0x72, 0x75, 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20,
+ 0x43, 0x41, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+ 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+ 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xda,
+ 0xcc, 0x18, 0x63, 0x30, 0xfd, 0xf4, 0x17, 0x23, 0x1a, 0x56, 0x7e, 0x5b,
+ 0xdf, 0x3c, 0x6c, 0x38, 0xe4, 0x71, 0xb7, 0x78, 0x91, 0xd4, 0xbc, 0xa1,
+ 0xd8, 0x4c, 0xf8, 0xa8, 0x43, 0xb6, 0x03, 0xe9, 0x4d, 0x21, 0x07, 0x08,
+ 0x88, 0xda, 0x58, 0x2f, 0x66, 0x39, 0x29, 0xbd, 0x05, 0x78, 0x8b, 0x9d,
+ 0x38, 0xe8, 0x05, 0xb7, 0x6a, 0x7e, 0x71, 0xa4, 0xe6, 0xc4, 0x60, 0xa6,
+ 0xb0, 0xef, 0x80, 0xe4, 0x89, 0x28, 0x0f, 0x9e, 0x25, 0xd6, 0xed, 0x83,
+ 0xf3, 0xad, 0xa6, 0x91, 0xc7, 0x98, 0xc9, 0x42, 0x18, 0x35, 0x14, 0x9d,
+ 0xad, 0x98, 0x46, 0x92, 0x2e, 0x4f, 0xca, 0xf1, 0x87, 0x43, 0xc1, 0x16,
+ 0x95, 0x57, 0x2d, 0x50, 0xef, 0x89, 0x2d, 0x80, 0x7a, 0x57, 0xad, 0xf2,
+ 0xee, 0x5f, 0x6b, 0xd2, 0x00, 0x8d, 0xb9, 0x14, 0xf8, 0x14, 0x15, 0x35,
+ 0xd9, 0xc0, 0x46, 0xa3, 0x7b, 0x72, 0xc8, 0x91, 0xbf, 0xc9, 0x55, 0x2b,
+ 0xcd, 0xd0, 0x97, 0x3e, 0x9c, 0x26, 0x64, 0xcc, 0xdf, 0xce, 0x83, 0x19,
+ 0x71, 0xca, 0x4e, 0xe6, 0xd4, 0xd5, 0x7b, 0xa9, 0x19, 0xcd, 0x55, 0xde,
+ 0xc8, 0xec, 0xd2, 0x5e, 0x38, 0x53, 0xe5, 0x5c, 0x4f, 0x8c, 0x2d, 0xfe,
+ 0x50, 0x23, 0x36, 0xfc, 0x66, 0xe6, 0xcb, 0x8e, 0xa4, 0x39, 0x19, 0x00,
+ 0xb7, 0x95, 0x02, 0x39, 0x91, 0x0b, 0x0e, 0xfe, 0x38, 0x2e, 0xd1, 0x1d,
+ 0x05, 0x9a, 0xf6, 0x4d, 0x3e, 0x6f, 0x0f, 0x07, 0x1d, 0xaf, 0x2c, 0x1e,
+ 0x8f, 0x60, 0x39, 0xe2, 0xfa, 0x36, 0x53, 0x13, 0x39, 0xd4, 0x5e, 0x26,
+ 0x2b, 0xdb, 0x3d, 0xa8, 0x14, 0xbd, 0x32, 0xeb, 0x18, 0x03, 0x28, 0x52,
+ 0x04, 0x71, 0xe5, 0xab, 0x33, 0x3d, 0xe1, 0x38, 0xbb, 0x07, 0x36, 0x84,
+ 0x62, 0x9c, 0x79, 0xea, 0x16, 0x30, 0xf4, 0x5f, 0xc0, 0x2b, 0xe8, 0x71,
+ 0x6b, 0xe4, 0xf9, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51,
+ 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05,
+ 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e,
+ 0x04, 0x16, 0x04, 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab,
+ 0x05, 0x64, 0x0c, 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c,
+ 0x11, 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x0d, 0x06,
+ 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00,
+ 0x03, 0x82, 0x01, 0x01, 0x00, 0x35, 0xe3, 0x29, 0x6a, 0xe5, 0x2f, 0x5d,
+ 0x54, 0x8e, 0x29, 0x50, 0x94, 0x9f, 0x99, 0x1a, 0x14, 0xe4, 0x8f, 0x78,
+ 0x2a, 0x62, 0x94, 0xa2, 0x27, 0x67, 0x9e, 0xd0, 0xcf, 0x1a, 0x5e, 0x47,
+ 0xe9, 0xc1, 0xb2, 0xa4, 0xcf, 0xdd, 0x41, 0x1a, 0x05, 0x4e, 0x9b, 0x4b,
+ 0xee, 0x4a, 0x6f, 0x55, 0x52, 0xb3, 0x24, 0xa1, 0x37, 0x0a, 0xeb, 0x64,
+ 0x76, 0x2a, 0x2e, 0x2c, 0xf3, 0xfd, 0x3b, 0x75, 0x90, 0xbf, 0xfa, 0x71,
+ 0xd8, 0xc7, 0x3d, 0x37, 0xd2, 0xb5, 0x05, 0x95, 0x62, 0xb9, 0xa6, 0xde,
+ 0x89, 0x3d, 0x36, 0x7b, 0x38, 0x77, 0x48, 0x97, 0xac, 0xa6, 0x20, 0x8f,
+ 0x2e, 0xa6, 0xc9, 0x0c, 0xc2, 0xb2, 0x99, 0x45, 0x00, 0xc7, 0xce, 0x11,
+ 0x51, 0x22, 0x22, 0xe0, 0xa5, 0xea, 0xb6, 0x15, 0x48, 0x09, 0x64, 0xea,
+ 0x5e, 0x4f, 0x74, 0xf7, 0x05, 0x3e, 0xc7, 0x8a, 0x52, 0x0c, 0xdb, 0x15,
+ 0xb4, 0xbd, 0x6d, 0x9b, 0xe5, 0xc6, 0xb1, 0x54, 0x68, 0xa9, 0xe3, 0x69,
+ 0x90, 0xb6, 0x9a, 0xa5, 0x0f, 0xb8, 0xb9, 0x3f, 0x20, 0x7d, 0xae, 0x4a,
+ 0xb5, 0xb8, 0x9c, 0xe4, 0x1d, 0xb6, 0xab, 0xe6, 0x94, 0xa5, 0xc1, 0xc7,
+ 0x83, 0xad, 0xdb, 0xf5, 0x27, 0x87, 0x0e, 0x04, 0x6c, 0xd5, 0xff, 0xdd,
+ 0xa0, 0x5d, 0xed, 0x87, 0x52, 0xb7, 0x2b, 0x15, 0x02, 0xae, 0x39, 0xa6,
+ 0x6a, 0x74, 0xe9, 0xda, 0xc4, 0xe7, 0xbc, 0x4d, 0x34, 0x1e, 0xa9, 0x5c,
+ 0x4d, 0x33, 0x5f, 0x92, 0x09, 0x2f, 0x88, 0x66, 0x5d, 0x77, 0x97, 0xc7,
+ 0x1d, 0x76, 0x13, 0xa9, 0xd5, 0xe5, 0xf1, 0x16, 0x09, 0x11, 0x35, 0xd5,
+ 0xac, 0xdb, 0x24, 0x71, 0x70, 0x2c, 0x98, 0x56, 0x0b, 0xd9, 0x17, 0xb4,
+ 0xd1, 0xe3, 0x51, 0x2b, 0x5e, 0x75, 0xe8, 0xd5, 0xd0, 0xdc, 0x4f, 0x34,
+ 0xed, 0xc2, 0x05, 0x66, 0x80, 0xa1, 0xcb, 0xe6, 0x33, 0x30, 0x82, 0x03,
+ 0xba, 0x30, 0x82, 0x02, 0xa2, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08,
+ 0x3e, 0xa3, 0xe4, 0x78, 0x99, 0x38, 0x13, 0x9d, 0x30, 0x0d, 0x06, 0x09,
+ 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30,
+ 0x49, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
+ 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13,
+ 0x0a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31,
+ 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
+ 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20,
+ 0x47, 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x34, 0x30, 0x37, 0x31, 0x36,
+ 0x31, 0x32, 0x32, 0x31, 0x34, 0x30, 0x5a, 0x17, 0x0d, 0x31, 0x34, 0x31,
+ 0x30, 0x31, 0x34, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x69,
+ 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
+ 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a,
+ 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f, 0x72, 0x6e, 0x69, 0x61, 0x31, 0x16,
+ 0x30, 0x14, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x4d, 0x6f, 0x75,
+ 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x56, 0x69, 0x65, 0x77, 0x31, 0x13,
+ 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x0a, 0x47, 0x6f, 0x6f,
+ 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x18, 0x30, 0x16, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x61, 0x69, 0x6c, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30,
+ 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08,
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
+ 0xb2, 0x68, 0x6e, 0x3f, 0x03, 0x9e, 0x43, 0x85, 0x16, 0xb7, 0x89, 0x0b,
+ 0x16, 0x2a, 0xbe, 0x26, 0x36, 0xdd, 0x68, 0x0a, 0x53, 0x4e, 0x20, 0x40,
+ 0xf8, 0xd1, 0xdd, 0x63, 0xcb, 0x46, 0x73, 0x09, 0x96, 0x36, 0xde, 0x2c,
+ 0x45, 0x71, 0x2e, 0x8a, 0x79, 0xeb, 0x40, 0x2f, 0x65, 0x83, 0x81, 0xdb,
+ 0x37, 0x03, 0x84, 0xa1, 0x9a, 0xd0, 0x22, 0x3b, 0x73, 0x38, 0x45, 0xd3,
+ 0xd5, 0x91, 0xb2, 0x52, 0xa3, 0x82, 0x01, 0x4f, 0x30, 0x82, 0x01, 0x4b,
+ 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x16, 0x30, 0x14, 0x06,
+ 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x30, 0x1a, 0x06, 0x03, 0x55,
+ 0x1d, 0x11, 0x04, 0x13, 0x30, 0x11, 0x82, 0x0f, 0x6d, 0x61, 0x69, 0x6c,
+ 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x30,
+ 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80,
+ 0x30, 0x68, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
+ 0x04, 0x5c, 0x30, 0x5a, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05,
+ 0x05, 0x07, 0x30, 0x02, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
+ 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49, 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72,
+ 0x74, 0x30, 0x2b, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
+ 0x01, 0x86, 0x1f, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x6c,
+ 0x69, 0x65, 0x6e, 0x74, 0x73, 0x31, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x30, 0x1d,
+ 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x75, 0xc6, 0xb0,
+ 0x4a, 0x46, 0x61, 0x83, 0xff, 0x91, 0x46, 0x45, 0x35, 0xa7, 0x0f, 0xd0,
+ 0x5b, 0xe9, 0xdd, 0x94, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
+ 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x1f, 0x06, 0x03, 0x55,
+ 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4a, 0xdd, 0x06, 0x16,
+ 0x1b, 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a,
+ 0xba, 0x5a, 0x81, 0x2f, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04,
+ 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
+ 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x30, 0x06, 0x03, 0x55, 0x1d, 0x1f,
+ 0x04, 0x29, 0x30, 0x27, 0x30, 0x25, 0xa0, 0x23, 0xa0, 0x21, 0x86, 0x1f,
+ 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x70, 0x6b, 0x69, 0x2e, 0x67,
+ 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x47, 0x49,
+ 0x41, 0x47, 0x32, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x7f, 0x41, 0xf5, 0x57, 0x18, 0x3c, 0x75, 0xf5, 0x23,
+ 0x66, 0xc3, 0xf0, 0xf2, 0x3e, 0x70, 0x34, 0x56, 0xca, 0x78, 0xec, 0xc7,
+ 0x81, 0x58, 0x0d, 0xdf, 0xf0, 0xfd, 0x86, 0xe6, 0xe6, 0x50, 0x3d, 0xf6,
+ 0x09, 0x9a, 0x4d, 0xca, 0x60, 0x37, 0x9a, 0xd4, 0xca, 0x51, 0x7c, 0xf0,
+ 0x66, 0x23, 0xea, 0x5e, 0x6a, 0x6f, 0x7b, 0xa6, 0x7a, 0x38, 0x97, 0x42,
+ 0x58, 0x1a, 0x1b, 0x42, 0xae, 0x28, 0xde, 0x18, 0x7f, 0xcc, 0x76, 0x18,
+ 0x58, 0x05, 0xbf, 0xea, 0xef, 0x14, 0xad, 0x34, 0xe5, 0x5f, 0x25, 0xab,
+ 0xa1, 0x5f, 0x78, 0x5b, 0x6f, 0xe6, 0x69, 0xd8, 0x74, 0x8c, 0x19, 0x59,
+ 0xb0, 0x1a, 0xfb, 0x8e, 0xdf, 0x61, 0xac, 0xeb, 0x2b, 0x0a, 0x1c, 0xab,
+ 0x30, 0x0d, 0x64, 0x25, 0x78, 0xdf, 0x81, 0x71, 0xe3, 0xbd, 0xde, 0x9c,
+ 0x3f, 0xdd, 0xe9, 0xf8, 0xb6, 0x98, 0x2d, 0x13, 0xa3, 0x7b, 0x14, 0x6f,
+ 0xe3, 0x8b, 0xfc, 0x4e, 0x31, 0x26, 0xba, 0x10, 0xb4, 0x12, 0xe9, 0xc9,
+ 0x49, 0x60, 0xf0, 0xaa, 0x1f, 0x44, 0x68, 0x19, 0xd2, 0xb3, 0xc8, 0x46,
+ 0x22, 0x6b, 0xe1, 0x21, 0x77, 0xfd, 0x72, 0x33, 0x13, 0x21, 0x27, 0x81,
+ 0xe4, 0x7a, 0xc9, 0xe4, 0x1c, 0x05, 0x04, 0x73, 0x13, 0xda, 0x47, 0xfe,
+ 0x59, 0x41, 0x9c, 0x11, 0xc5, 0xf6, 0xb5, 0xd0, 0x01, 0xcb, 0x40, 0x19,
+ 0xf5, 0xfe, 0xb3, 0x3c, 0x1f, 0x61, 0x8f, 0x4d, 0xdb, 0x81, 0x2a, 0x8a,
+ 0xed, 0xb8, 0x53, 0xc7, 0x19, 0x6b, 0xfa, 0x8b, 0xfc, 0xe3, 0x2e, 0x12,
+ 0x4e, 0xbd, 0xc5, 0x44, 0x9d, 0x1c, 0x7f, 0x3b, 0x09, 0x51, 0xd7, 0x0a,
+ 0x0f, 0x22, 0x0a, 0xfd, 0x8c, 0x90, 0x14, 0xed, 0x10, 0xcb, 0x50, 0xcf,
+ 0xa5, 0x45, 0xce, 0xb0, 0x21, 0x28, 0xcb, 0xd6, 0xf5, 0x6e, 0xb2, 0x3e,
+ 0xfa, 0x35, 0x0c, 0x3d, 0x09, 0x0d, 0x81, 0x30, 0x82, 0x04, 0x04, 0x30,
+ 0x82, 0x02, 0xec, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x03, 0x02, 0x3a,
+ 0x69, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x05, 0x05, 0x00, 0x30, 0x42, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x16, 0x30, 0x14, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0d, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x1b, 0x30, 0x19, 0x06,
+ 0x03, 0x55, 0x04, 0x03, 0x13, 0x12, 0x47, 0x65, 0x6f, 0x54, 0x72, 0x75,
+ 0x73, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x43, 0x41,
+ 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x34, 0x30, 0x35, 0x31, 0x35,
+ 0x31, 0x35, 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x30, 0x34, 0x30,
+ 0x34, 0x31, 0x35, 0x31, 0x35, 0x35, 0x35, 0x5a, 0x30, 0x49, 0x31, 0x0b,
+ 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0a, 0x47, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x25, 0x30, 0x23,
+ 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1c, 0x47, 0x6f, 0x6f, 0x67, 0x6c,
+ 0x65, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x41,
+ 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x47, 0x32, 0x30,
+ 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+ 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30,
+ 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9c, 0x2a, 0x04, 0x77,
+ 0x5c, 0xd8, 0x50, 0x91, 0x3a, 0x06, 0xa3, 0x82, 0xe0, 0xd8, 0x50, 0x48,
+ 0xbc, 0x89, 0x3f, 0xf1, 0x19, 0x70, 0x1a, 0x88, 0x46, 0x7e, 0xe0, 0x8f,
+ 0xc5, 0xf1, 0x89, 0xce, 0x21, 0xee, 0x5a, 0xfe, 0x61, 0x0d, 0xb7, 0x32,
+ 0x44, 0x89, 0xa0, 0x74, 0x0b, 0x53, 0x4f, 0x55, 0xa4, 0xce, 0x82, 0x62,
+ 0x95, 0xee, 0xeb, 0x59, 0x5f, 0xc6, 0xe1, 0x05, 0x80, 0x12, 0xc4, 0x5e,
+ 0x94, 0x3f, 0xbc, 0x5b, 0x48, 0x38, 0xf4, 0x53, 0xf7, 0x24, 0xe6, 0xfb,
+ 0x91, 0xe9, 0x15, 0xc4, 0xcf, 0xf4, 0x53, 0x0d, 0xf4, 0x4a, 0xfc, 0x9f,
+ 0x54, 0xde, 0x7d, 0xbe, 0xa0, 0x6b, 0x6f, 0x87, 0xc0, 0xd0, 0x50, 0x1f,
+ 0x28, 0x30, 0x03, 0x40, 0xda, 0x08, 0x73, 0x51, 0x6c, 0x7f, 0xff, 0x3a,
+ 0x3c, 0xa7, 0x37, 0x06, 0x8e, 0xbd, 0x4b, 0x11, 0x04, 0xeb, 0x7d, 0x24,
+ 0xde, 0xe6, 0xf9, 0xfc, 0x31, 0x71, 0xfb, 0x94, 0xd5, 0x60, 0xf3, 0x2e,
+ 0x4a, 0xaf, 0x42, 0xd2, 0xcb, 0xea, 0xc4, 0x6a, 0x1a, 0xb2, 0xcc, 0x53,
+ 0xdd, 0x15, 0x4b, 0x8b, 0x1f, 0xc8, 0x19, 0x61, 0x1f, 0xcd, 0x9d, 0xa8,
+ 0x3e, 0x63, 0x2b, 0x84, 0x35, 0x69, 0x65, 0x84, 0xc8, 0x19, 0xc5, 0x46,
+ 0x22, 0xf8, 0x53, 0x95, 0xbe, 0xe3, 0x80, 0x4a, 0x10, 0xc6, 0x2a, 0xec,
+ 0xba, 0x97, 0x20, 0x11, 0xc7, 0x39, 0x99, 0x10, 0x04, 0xa0, 0xf0, 0x61,
+ 0x7a, 0x95, 0x25, 0x8c, 0x4e, 0x52, 0x75, 0xe2, 0xb6, 0xed, 0x08, 0xca,
+ 0x14, 0xfc, 0xce, 0x22, 0x6a, 0xb3, 0x4e, 0xcf, 0x46, 0x03, 0x97, 0x97,
+ 0x03, 0x7e, 0xc0, 0xb1, 0xde, 0x7b, 0xaf, 0x45, 0x33, 0xcf, 0xba, 0x3e,
+ 0x71, 0xb7, 0xde, 0xf4, 0x25, 0x25, 0xc2, 0x0d, 0x35, 0x89, 0x9d, 0x9d,
+ 0xfb, 0x0e, 0x11, 0x79, 0x89, 0x1e, 0x37, 0xc5, 0xaf, 0x8e, 0x72, 0x69,
+ 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xfb, 0x30, 0x81, 0xf8, 0x30,
+ 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
+ 0xc0, 0x7a, 0x98, 0x68, 0x8d, 0x89, 0xfb, 0xab, 0x05, 0x64, 0x0c, 0x11,
+ 0x7d, 0xaa, 0x7d, 0x65, 0xb8, 0xca, 0xcc, 0x4e, 0x30, 0x1d, 0x06, 0x03,
+ 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0xdd, 0x06, 0x16, 0x1b,
+ 0xbc, 0xf6, 0x68, 0xb5, 0x76, 0xf5, 0x81, 0xb6, 0xbb, 0x62, 0x1a, 0xba,
+ 0x5a, 0x81, 0x2f, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
+ 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x00, 0x30,
+ 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
+ 0x02, 0x01, 0x06, 0x30, 0x3a, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x33,
+ 0x30, 0x31, 0x30, 0x2f, 0xa0, 0x2d, 0xa0, 0x2b, 0x86, 0x29, 0x68, 0x74,
+ 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x67, 0x65, 0x6f,
+ 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72,
+ 0x6c, 0x73, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x2e,
+ 0x63, 0x72, 0x6c, 0x30, 0x3d, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05,
+ 0x07, 0x01, 0x01, 0x04, 0x31, 0x30, 0x2f, 0x30, 0x2d, 0x06, 0x08, 0x2b,
+ 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x21, 0x68, 0x74, 0x74,
+ 0x70, 0x3a, 0x2f, 0x2f, 0x67, 0x74, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c,
+ 0x2d, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x67, 0x65, 0x6f, 0x74, 0x72, 0x75,
+ 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d,
+ 0x20, 0x04, 0x10, 0x30, 0x0e, 0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01,
+ 0x04, 0x01, 0xd6, 0x79, 0x02, 0x05, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+ 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82,
+ 0x01, 0x01, 0x00, 0x36, 0xd7, 0x06, 0x80, 0x11, 0x27, 0xad, 0x2a, 0x14,
+ 0x9b, 0x38, 0x77, 0xb3, 0x23, 0xa0, 0x75, 0x58, 0xbb, 0xb1, 0x7e, 0x83,
+ 0x42, 0xba, 0x72, 0xda, 0x1e, 0xd8, 0x8e, 0x36, 0x06, 0x97, 0xe0, 0xf0,
+ 0x95, 0x3b, 0x37, 0xfd, 0x1b, 0x42, 0x58, 0xfe, 0x22, 0xc8, 0x6b, 0xbd,
+ 0x38, 0x5e, 0xd1, 0x3b, 0x25, 0x6e, 0x12, 0xeb, 0x5e, 0x67, 0x76, 0x46,
+ 0x40, 0x90, 0xda, 0x14, 0xc8, 0x78, 0x0d, 0xed, 0x95, 0x66, 0xda, 0x8e,
+ 0x86, 0x6f, 0x80, 0xa1, 0xba, 0x56, 0x32, 0x95, 0x86, 0xdc, 0xdc, 0x6a,
+ 0xca, 0x04, 0x8c, 0x5b, 0x7f, 0xf6, 0xbf, 0xcc, 0x6f, 0x85, 0x03, 0x58,
+ 0xc3, 0x68, 0x51, 0x13, 0xcd, 0xfd, 0xc8, 0xf7, 0x79, 0x3d, 0x99, 0x35,
+ 0xf0, 0x56, 0xa3, 0xbd, 0xe0, 0x59, 0xed, 0x4f, 0x44, 0x09, 0xa3, 0x9e,
+ 0x38, 0x7a, 0xf6, 0x46, 0xd1, 0x1d, 0x12, 0x9d, 0x4f, 0xbe, 0xd0, 0x40,
+ 0xfc, 0x55, 0xfe, 0x06, 0x5e, 0x3c, 0xda, 0x1c, 0x56, 0xbd, 0x96, 0x51,
+ 0x7b, 0x6f, 0x57, 0x2a, 0xdb, 0xa2, 0xaa, 0x96, 0xdc, 0x8c, 0x74, 0xc2,
+ 0x95, 0xbe, 0xf0, 0x6e, 0x95, 0x13, 0xff, 0x17, 0xf0, 0x3c, 0xac, 0xb2,
+ 0x10, 0x8d, 0xcc, 0x73, 0xfb, 0xe8, 0x8f, 0x02, 0xc6, 0xf0, 0xfb, 0x33,
+ 0xb3, 0x95, 0x3b, 0xe3, 0xc2, 0xcb, 0x68, 0x58, 0x73, 0xdb, 0xa8, 0x24,
+ 0x62, 0x3b, 0x06, 0x35, 0x9d, 0x0d, 0xa9, 0x33, 0xbd, 0x78, 0x03, 0x90,
+ 0x2e, 0x4c, 0x78, 0x5d, 0x50, 0x3a, 0x81, 0xd4, 0xee, 0xa0, 0xc8, 0x70,
+ 0x38, 0xdc, 0xb2, 0xf9, 0x67, 0xfa, 0x87, 0x40, 0x5d, 0x61, 0xc0, 0x51,
+ 0x8f, 0x6b, 0x83, 0x6b, 0xcd, 0x05, 0x3a, 0xca, 0xe1, 0xa7, 0x05, 0x78,
+ 0xfc, 0xca, 0xda, 0x94, 0xd0, 0x2c, 0x08, 0x3d, 0x7e, 0x16, 0x79, 0xc8,
+ 0xa0, 0x50, 0x20, 0x24, 0x54, 0x33, 0x71, 0x31, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00,
+};
+
+/* kPKCS7Windows is the Equifax root certificate, as exported by Windows 7. */
+static const uint8_t kPKCS7Windows[] = {
+ 0x30, 0x82, 0x02, 0xb1, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+ 0x01, 0x07, 0x02, 0xa0, 0x82, 0x02, 0xa2, 0x30, 0x82, 0x02, 0x9e, 0x02,
+ 0x01, 0x01, 0x31, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82, 0x02, 0x86, 0x30, 0x82, 0x02,
+ 0x82, 0x30, 0x82, 0x01, 0xeb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01,
+ 0x04, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+ 0x01, 0x04, 0x05, 0x00, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06,
+ 0x03, 0x55, 0x04, 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61,
+ 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63,
+ 0x2e, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d,
+ 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75,
+ 0x72, 0x65, 0x20, 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73,
+ 0x20, 0x43, 0x41, 0x2d, 0x31, 0x30, 0x1e, 0x17, 0x0d, 0x39, 0x39, 0x30,
+ 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d,
+ 0x32, 0x30, 0x30, 0x36, 0x32, 0x31, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30,
+ 0x5a, 0x30, 0x53, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06,
+ 0x13, 0x02, 0x55, 0x53, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
+ 0x0a, 0x13, 0x13, 0x45, 0x71, 0x75, 0x69, 0x66, 0x61, 0x78, 0x20, 0x53,
+ 0x65, 0x63, 0x75, 0x72, 0x65, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x26,
+ 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1d, 0x45, 0x71, 0x75,
+ 0x69, 0x66, 0x61, 0x78, 0x20, 0x53, 0x65, 0x63, 0x75, 0x72, 0x65, 0x20,
+ 0x65, 0x42, 0x75, 0x73, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x20, 0x43, 0x41,
+ 0x2d, 0x31, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
+ 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
+ 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xce, 0x2f, 0x19, 0xbc, 0x17,
+ 0xb7, 0x77, 0xde, 0x93, 0xa9, 0x5f, 0x5a, 0x0d, 0x17, 0x4f, 0x34, 0x1a,
+ 0x0c, 0x98, 0xf4, 0x22, 0xd9, 0x59, 0xd4, 0xc4, 0x68, 0x46, 0xf0, 0xb4,
+ 0x35, 0xc5, 0x85, 0x03, 0x20, 0xc6, 0xaf, 0x45, 0xa5, 0x21, 0x51, 0x45,
+ 0x41, 0xeb, 0x16, 0x58, 0x36, 0x32, 0x6f, 0xe2, 0x50, 0x62, 0x64, 0xf9,
+ 0xfd, 0x51, 0x9c, 0xaa, 0x24, 0xd9, 0xf4, 0x9d, 0x83, 0x2a, 0x87, 0x0a,
+ 0x21, 0xd3, 0x12, 0x38, 0x34, 0x6c, 0x8d, 0x00, 0x6e, 0x5a, 0xa0, 0xd9,
+ 0x42, 0xee, 0x1a, 0x21, 0x95, 0xf9, 0x52, 0x4c, 0x55, 0x5a, 0xc5, 0x0f,
+ 0x38, 0x4f, 0x46, 0xfa, 0x6d, 0xf8, 0x2e, 0x35, 0xd6, 0x1d, 0x7c, 0xeb,
+ 0xe2, 0xf0, 0xb0, 0x75, 0x80, 0xc8, 0xa9, 0x13, 0xac, 0xbe, 0x88, 0xef,
+ 0x3a, 0x6e, 0xab, 0x5f, 0x2a, 0x38, 0x62, 0x02, 0xb0, 0x12, 0x7b, 0xfe,
+ 0x8f, 0xa6, 0x03, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x66, 0x30, 0x64,
+ 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
+ 0x01, 0x04, 0x04, 0x03, 0x02, 0x00, 0x07, 0x30, 0x0f, 0x06, 0x03, 0x55,
+ 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+ 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80,
+ 0x14, 0x4a, 0x78, 0x32, 0x52, 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf,
+ 0xc1, 0x14, 0x36, 0x40, 0x6a, 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x1d, 0x06,
+ 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4a, 0x78, 0x32, 0x52,
+ 0x11, 0xdb, 0x59, 0x16, 0x36, 0x5e, 0xdf, 0xc1, 0x14, 0x36, 0x40, 0x6a,
+ 0x47, 0x7c, 0x4c, 0xa1, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x75,
+ 0x5b, 0xa8, 0x9b, 0x03, 0x11, 0xe6, 0xe9, 0x56, 0x4c, 0xcd, 0xf9, 0xa9,
+ 0x4c, 0xc0, 0x0d, 0x9a, 0xf3, 0xcc, 0x65, 0x69, 0xe6, 0x25, 0x76, 0xcc,
+ 0x59, 0xb7, 0xd6, 0x54, 0xc3, 0x1d, 0xcd, 0x99, 0xac, 0x19, 0xdd, 0xb4,
+ 0x85, 0xd5, 0xe0, 0x3d, 0xfc, 0x62, 0x20, 0xa7, 0x84, 0x4b, 0x58, 0x65,
+ 0xf1, 0xe2, 0xf9, 0x95, 0x21, 0x3f, 0xf5, 0xd4, 0x7e, 0x58, 0x1e, 0x47,
+ 0x87, 0x54, 0x3e, 0x58, 0xa1, 0xb5, 0xb5, 0xf8, 0x2a, 0xef, 0x71, 0xe7,
+ 0xbc, 0xc3, 0xf6, 0xb1, 0x49, 0x46, 0xe2, 0xd7, 0xa0, 0x6b, 0xe5, 0x56,
+ 0x7a, 0x9a, 0x27, 0x98, 0x7c, 0x46, 0x62, 0x14, 0xe7, 0xc9, 0xfc, 0x6e,
+ 0x03, 0x12, 0x79, 0x80, 0x38, 0x1d, 0x48, 0x82, 0x8d, 0xfc, 0x17, 0xfe,
+ 0x2a, 0x96, 0x2b, 0xb5, 0x62, 0xa6, 0xa6, 0x3d, 0xbd, 0x7f, 0x92, 0x59,
+ 0xcd, 0x5a, 0x2a, 0x82, 0xb2, 0x37, 0x79, 0x31, 0x00,
+};
+
+static int test_reparse(const uint8_t *der_bytes, size_t der_len) {
+ CBS pkcs7;
+ CBB cbb;
+ STACK_OF(X509) *certs = sk_X509_new_null();
+ STACK_OF(X509) *certs2 = sk_X509_new_null();
+ uint8_t *result_data, *result2_data;
+ size_t result_len, result2_len, i;
+
+ CBS_init(&pkcs7, der_bytes, der_len);
+ if (!PKCS7_get_certificates(certs, &pkcs7)) {
+ fprintf(stderr, "PKCS7_get_certificates failed.\n");
+ return 0;
+ }
+
+ CBB_init(&cbb, der_len);
+ if (!PKCS7_bundle_certificates(&cbb, certs) ||
+ !CBB_finish(&cbb, &result_data, &result_len)) {
+ fprintf(stderr, "PKCS7_bundle_certificates failed.\n");
+ return 0;
+ }
+
+ CBS_init(&pkcs7, result_data, result_len);
+ if (!PKCS7_get_certificates(certs2, &pkcs7)) {
+ fprintf(stderr, "PKCS7_get_certificates reparse failed.\n");
+ return 0;
+ }
+
+ if (sk_X509_num(certs) != sk_X509_num(certs2)) {
+ fprintf(stderr, "Number of certs in results differ.\n");
+ return 0;
+ }
+
+ for (i = 0; i < sk_X509_num(certs); i++) {
+ X509 *a = sk_X509_value(certs, i);
+ X509 *b = sk_X509_value(certs2, i);
+
+ if (X509_cmp(a, b) != 0) {
+ fprintf(stderr, "Certificate %u differs.\n", (unsigned) i);
+ return 0;
+ }
+ }
+
+ CBB_init(&cbb, der_len);
+ if (!PKCS7_bundle_certificates(&cbb, certs2) ||
+ !CBB_finish(&cbb, &result2_data, &result2_len)) {
+ fprintf(stderr,
+ "PKCS7_bundle_certificates failed the second time.\n");
+ return 0;
+ }
+
+ if (result_len != result2_len ||
+ memcmp(result_data, result2_data, result_len) != 0) {
+ fprintf(stderr, "Serialisation is not stable.\n");
+ return 0;
+ }
+
+ OPENSSL_free(result_data);
+ OPENSSL_free(result2_data);
+ sk_X509_pop_free(certs, X509_free);
+ sk_X509_pop_free(certs2, X509_free);
+
+ return 1;
+}
+
+int main(void) {
+ CRYPTO_library_init();
+
+ if (!test_reparse(kPKCS7NSS, sizeof(kPKCS7NSS)) ||
+ !test_reparse(kPKCS7Windows, sizeof(kPKCS7Windows))) {
+ return 1;
+ }
+
+ printf("PASS\n");
+ return 0;
+}
+
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
new file mode 100644
index 0000000..93a7afb
--- /dev/null
+++ b/src/crypto/x509/t_crl.c
@@ -0,0 +1,129 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+#ifndef OPENSSL_NO_FP_API
+int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
+ {
+ BIO *b;
+ int ret;
+
+ if ((b=BIO_new(BIO_s_file())) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_print_fp, ERR_R_BUF_LIB);
+ return(0);
+ }
+ BIO_set_fp(b,fp,BIO_NOCLOSE);
+ ret=X509_CRL_print(b, x);
+ BIO_free(b);
+ return(ret);
+ }
+#endif
+
+int X509_CRL_print(BIO *out, X509_CRL *x)
+{
+ STACK_OF(X509_REVOKED) *rev;
+ X509_REVOKED *r;
+ long l;
+ size_t i;
+ char *p;
+
+ BIO_printf(out, "Certificate Revocation List (CRL):\n");
+ l = X509_CRL_get_version(x);
+ BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
+ X509_signature_print(out, x->sig_alg, NULL);
+ p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
+ BIO_printf(out,"%8sIssuer: %s\n","",p);
+ OPENSSL_free(p);
+ BIO_printf(out,"%8sLast Update: ","");
+ ASN1_TIME_print(out,X509_CRL_get_lastUpdate(x));
+ BIO_printf(out,"\n%8sNext Update: ","");
+ if (X509_CRL_get_nextUpdate(x))
+ ASN1_TIME_print(out,X509_CRL_get_nextUpdate(x));
+ else BIO_printf(out,"NONE");
+ BIO_printf(out,"\n");
+
+ X509V3_extensions_print(out, "CRL extensions",
+ x->crl->extensions, 0, 8);
+
+ rev = X509_CRL_get_REVOKED(x);
+
+ if(sk_X509_REVOKED_num(rev) > 0)
+ BIO_printf(out, "Revoked Certificates:\n");
+ else BIO_printf(out, "No Revoked Certificates.\n");
+
+ for(i = 0; i < sk_X509_REVOKED_num(rev); i++) {
+ r = sk_X509_REVOKED_value(rev, i);
+ BIO_printf(out," Serial Number: ");
+ i2a_ASN1_INTEGER(out,r->serialNumber);
+ BIO_printf(out,"\n Revocation Date: ");
+ ASN1_TIME_print(out,r->revocationDate);
+ BIO_printf(out,"\n");
+ X509V3_extensions_print(out, "CRL entry extensions",
+ r->extensions, 0, 8);
+ }
+ X509_signature_print(out, x->sig_alg, x->signature);
+
+ return 1;
+
+}
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
new file mode 100644
index 0000000..2b9a421
--- /dev/null
+++ b/src/crypto/x509/t_x509.c
@@ -0,0 +1,500 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "../evp/internal.h"
+
+#ifndef OPENSSL_NO_FP_API
+int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
+ {
+ BIO *b;
+ int ret;
+
+ if ((b=BIO_new(BIO_s_file())) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_print_ex_fp, ERR_R_BUF_LIB);
+ return(0);
+ }
+ BIO_set_fp(b,fp,BIO_NOCLOSE);
+ ret=X509_print_ex(b, x, nmflag, cflag);
+ BIO_free(b);
+ return(ret);
+ }
+
+int X509_print_fp(FILE *fp, X509 *x)
+ {
+ return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+ }
+#endif
+
+int X509_print(BIO *bp, X509 *x)
+{
+ return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
+
+int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
+ {
+ long l;
+ int ret=0,i;
+ char *m=NULL,mlch = ' ';
+ int nmindent = 0;
+ X509_CINF *ci;
+ ASN1_INTEGER *bs;
+ EVP_PKEY *pkey=NULL;
+ const char *neg;
+
+ if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+ mlch = '\n';
+ nmindent = 12;
+ }
+
+ if(nmflags == X509_FLAG_COMPAT)
+ nmindent = 16;
+
+ ci=x->cert_info;
+ if(!(cflag & X509_FLAG_NO_HEADER))
+ {
+ if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
+ if (BIO_write(bp," Data:\n",10) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_VERSION))
+ {
+ l=X509_get_version(x);
+ if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_SERIAL))
+ {
+
+ if (BIO_write(bp," Serial Number:",22) <= 0) goto err;
+
+ bs=X509_get_serialNumber(x);
+ if (bs->length <= (int)sizeof(long))
+ {
+ l=ASN1_INTEGER_get(bs);
+ if (bs->type == V_ASN1_NEG_INTEGER)
+ {
+ l= -l;
+ neg="-";
+ }
+ else
+ neg="";
+ if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
+ goto err;
+ }
+ else
+ {
+ neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
+ if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
+
+ for (i=0; i<bs->length; i++)
+ {
+ if (BIO_printf(bp,"%02x%c",bs->data[i],
+ ((i+1 == bs->length)?'\n':':')) <= 0)
+ goto err;
+ }
+ }
+
+ }
+
+ if(!(cflag & X509_FLAG_NO_SIGNAME))
+ {
+ if (X509_signature_print(bp, ci->signature, NULL) <= 0)
+ goto err;
+ }
+
+ if(!(cflag & X509_FLAG_NO_ISSUER))
+ {
+ if (BIO_printf(bp," Issuer:%c",mlch) <= 0) goto err;
+ if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
+ if (BIO_write(bp,"\n",1) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_VALIDITY))
+ {
+ if (BIO_write(bp," Validity\n",17) <= 0) goto err;
+ if (BIO_write(bp," Not Before: ",24) <= 0) goto err;
+ if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
+ if (BIO_write(bp,"\n Not After : ",25) <= 0) goto err;
+ if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
+ if (BIO_write(bp,"\n",1) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_SUBJECT))
+ {
+ if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err;
+ if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
+ if (BIO_write(bp,"\n",1) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_PUBKEY))
+ {
+ if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0)
+ goto err;
+ if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
+ goto err;
+ if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
+ goto err;
+ if (BIO_puts(bp, "\n") <= 0)
+ goto err;
+
+ pkey=X509_get_pubkey(x);
+ if (pkey == NULL)
+ {
+ BIO_printf(bp,"%12sUnable to load Public Key\n","");
+ BIO_print_errors(bp);
+ }
+ else
+ {
+ EVP_PKEY_print_public(bp, pkey, 16, NULL);
+ EVP_PKEY_free(pkey);
+ }
+ }
+
+ if(!(cflag & X509_FLAG_NO_IDS))
+ {
+ if (ci->issuerUID)
+ {
+ if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->issuerUID, 12))
+ goto err;
+ }
+ if (ci->subjectUID)
+ {
+ if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0)
+ goto err;
+ if (!X509_signature_dump(bp, ci->subjectUID, 12))
+ goto err;
+ }
+ }
+
+ if (!(cflag & X509_FLAG_NO_EXTENSIONS))
+ X509V3_extensions_print(bp, "X509v3 extensions",
+ ci->extensions, cflag, 8);
+
+ if(!(cflag & X509_FLAG_NO_SIGDUMP))
+ {
+ if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
+ }
+ if(!(cflag & X509_FLAG_NO_AUX))
+ {
+ if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
+ }
+ ret=1;
+err:
+ if (m != NULL) OPENSSL_free(m);
+ return(ret);
+ }
+
+int X509_ocspid_print (BIO *bp, X509 *x)
+ {
+ unsigned char *der=NULL ;
+ unsigned char *dertmp;
+ int derlen;
+ int i;
+ unsigned char SHA1md[SHA_DIGEST_LENGTH];
+
+ /* display the hash of the subject as it would appear
+ in OCSP requests */
+ if (BIO_printf(bp," Subject OCSP hash: ") <= 0)
+ goto err;
+ derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
+ if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
+ goto err;
+ i2d_X509_NAME(x->cert_info->subject, &dertmp);
+
+ if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+ goto err;
+ for (i=0; i < SHA_DIGEST_LENGTH; i++)
+ {
+ if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
+ }
+ OPENSSL_free (der);
+ der=NULL;
+
+ /* display the hash of the public key as it would appear
+ in OCSP requests */
+ if (BIO_printf(bp,"\n Public key OCSP hash: ") <= 0)
+ goto err;
+
+ if (!EVP_Digest(x->cert_info->key->public_key->data,
+ x->cert_info->key->public_key->length,
+ SHA1md, NULL, EVP_sha1(), NULL))
+ goto err;
+ for (i=0; i < SHA_DIGEST_LENGTH; i++)
+ {
+ if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
+ goto err;
+ }
+ BIO_printf(bp,"\n");
+
+ return (1);
+err:
+ if (der != NULL) OPENSSL_free(der);
+ return(0);
+ }
+
+int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
+{
+ int sig_nid;
+ if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0;
+ if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
+
+ sig_nid = OBJ_obj2nid(sigalg->algorithm);
+ if (sig_nid != NID_undef)
+ {
+ int pkey_nid, dig_nid;
+ const EVP_PKEY_ASN1_METHOD *ameth;
+ if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid))
+ {
+ ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
+ if (ameth && ameth->sig_print)
+ return ameth->sig_print(bp, sigalg, sig, 9, 0);
+ }
+ }
+ if (sig)
+ return X509_signature_dump(bp, sig, 9);
+ else if (BIO_puts(bp, "\n") <= 0)
+ return 0;
+ return 1;
+}
+
+int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
+ {
+ int i,n;
+ char buf[80];
+ const char *p;
+
+ if (v == NULL) return(0);
+ n=0;
+ p=(const char *)v->data;
+ for (i=0; i<v->length; i++)
+ {
+ if ((p[i] > '~') || ((p[i] < ' ') &&
+ (p[i] != '\n') && (p[i] != '\r')))
+ buf[n]='.';
+ else
+ buf[n]=p[i];
+ n++;
+ if (n >= 80)
+ {
+ if (BIO_write(bp,buf,n) <= 0)
+ return(0);
+ n=0;
+ }
+ }
+ if (n > 0)
+ if (BIO_write(bp,buf,n) <= 0)
+ return(0);
+ return(1);
+ }
+
+int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
+{
+ if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
+ if(tm->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_print(bp, tm);
+ BIO_write(bp,"Bad time value",14);
+ return(0);
+}
+
+static const char *const mon[12]=
+ {
+ "Jan","Feb","Mar","Apr","May","Jun",
+ "Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+
+int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
+ {
+ char *v;
+ int gmt=0;
+ int i;
+ int y=0,M=0,d=0,h=0,m=0,s=0;
+ char *f = NULL;
+ int f_len = 0;
+
+ i=tm->length;
+ v=(char *)tm->data;
+
+ if (i < 12) goto err;
+ if (v[i-1] == 'Z') gmt=1;
+ for (i=0; i<12; i++)
+ if ((v[i] > '9') || (v[i] < '0')) goto err;
+ y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
+ M= (v[4]-'0')*10+(v[5]-'0');
+ if ((M > 12) || (M < 1)) goto err;
+ d= (v[6]-'0')*10+(v[7]-'0');
+ h= (v[8]-'0')*10+(v[9]-'0');
+ m= (v[10]-'0')*10+(v[11]-'0');
+ if (tm->length >= 14 &&
+ (v[12] >= '0') && (v[12] <= '9') &&
+ (v[13] >= '0') && (v[13] <= '9'))
+ {
+ s= (v[12]-'0')*10+(v[13]-'0');
+ /* Check for fractions of seconds. */
+ if (tm->length >= 15 && v[14] == '.')
+ {
+ int l = tm->length;
+ f = &v[14]; /* The decimal point. */
+ f_len = 1;
+ while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
+ ++f_len;
+ }
+ }
+
+ if (BIO_printf(bp,"%s %2d %02d:%02d:%02d%.*s %d%s",
+ mon[M-1],d,h,m,s,f_len,f,y,(gmt)?" GMT":"") <= 0)
+ return(0);
+ else
+ return(1);
+err:
+ BIO_write(bp,"Bad time value",14);
+ return(0);
+ }
+
+int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
+ {
+ const char *v;
+ int gmt=0;
+ int i;
+ int y=0,M=0,d=0,h=0,m=0,s=0;
+
+ i=tm->length;
+ v=(const char *)tm->data;
+
+ if (i < 10) goto err;
+ if (v[i-1] == 'Z') gmt=1;
+ for (i=0; i<10; i++)
+ if ((v[i] > '9') || (v[i] < '0')) goto err;
+ y= (v[0]-'0')*10+(v[1]-'0');
+ if (y < 50) y+=100;
+ M= (v[2]-'0')*10+(v[3]-'0');
+ if ((M > 12) || (M < 1)) goto err;
+ d= (v[4]-'0')*10+(v[5]-'0');
+ h= (v[6]-'0')*10+(v[7]-'0');
+ m= (v[8]-'0')*10+(v[9]-'0');
+ if (tm->length >=12 &&
+ (v[10] >= '0') && (v[10] <= '9') &&
+ (v[11] >= '0') && (v[11] <= '9'))
+ s= (v[10]-'0')*10+(v[11]-'0');
+
+ if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
+ mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
+ return(0);
+ else
+ return(1);
+err:
+ BIO_write(bp,"Bad time value",14);
+ return(0);
+ }
+
+int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
+ {
+ char *s,*c,*b;
+ int ret=0,l,i;
+
+ l=80-2-obase;
+
+ b=X509_NAME_oneline(name,NULL,0);
+ if (!b)
+ return 0;
+ if (!*b)
+ {
+ OPENSSL_free(b);
+ return 1;
+ }
+ s=b+1; /* skip the first slash */
+
+ c=s;
+ for (;;)
+ {
+ if ( ((*s == '/') &&
+ ((s[1] >= 'A') && (s[1] <= 'Z') && (
+ (s[2] == '=') ||
+ ((s[2] >= 'A') && (s[2] <= 'Z') &&
+ (s[3] == '='))
+ ))) ||
+ (*s == '\0'))
+ {
+ i=s-c;
+ if (BIO_write(bp,c,i) != i) goto err;
+ c=s+1; /* skip following slash */
+ if (*s != '\0')
+ {
+ if (BIO_write(bp,", ",2) != 2) goto err;
+ }
+ l--;
+ }
+ if (*s == '\0') break;
+ s++;
+ l--;
+ }
+
+ ret=1;
+ if (0)
+ {
+err:
+ OPENSSL_PUT_ERROR(X509, X509_NAME_print, ERR_R_BUF_LIB);
+ }
+ OPENSSL_free(b);
+ return(ret);
+ }
diff --git a/src/crypto/x509/t_x509a.c b/src/crypto/x509/t_x509a.c
new file mode 100644
index 0000000..7667268
--- /dev/null
+++ b/src/crypto/x509/t_x509a.c
@@ -0,0 +1,109 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+/* X509_CERT_AUX and string set routines */
+
+int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
+{
+ char oidstr[80], first;
+ size_t i;
+ int j;
+ if(!aux) return 1;
+ if(aux->trust) {
+ first = 1;
+ BIO_printf(out, "%*sTrusted Uses:\n%*s",
+ indent, "", indent + 2, "");
+ for(i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
+ if(!first) BIO_puts(out, ", ");
+ else first = 0;
+ OBJ_obj2txt(oidstr, sizeof oidstr,
+ sk_ASN1_OBJECT_value(aux->trust, i), 0);
+ BIO_puts(out, oidstr);
+ }
+ BIO_puts(out, "\n");
+ } else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
+ if(aux->reject) {
+ first = 1;
+ BIO_printf(out, "%*sRejected Uses:\n%*s",
+ indent, "", indent + 2, "");
+ for(i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
+ if(!first) BIO_puts(out, ", ");
+ else first = 0;
+ OBJ_obj2txt(oidstr, sizeof oidstr,
+ sk_ASN1_OBJECT_value(aux->reject, i), 0);
+ BIO_puts(out, oidstr);
+ }
+ BIO_puts(out, "\n");
+ } else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
+ if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "",
+ aux->alias->data);
+ if(aux->keyid) {
+ BIO_printf(out, "%*sKey Id: ", indent, "");
+ for(j = 0; j < aux->keyid->length; j++)
+ BIO_printf(out, "%s%02X",
+ j ? ":" : "",
+ aux->keyid->data[j]);
+ BIO_write(out,"\n",1);
+ }
+ return 1;
+}
diff --git a/src/crypto/x509/vpm_int.h b/src/crypto/x509/vpm_int.h
new file mode 100644
index 0000000..d18a4d4
--- /dev/null
+++ b/src/crypto/x509/vpm_int.h
@@ -0,0 +1,70 @@
+/* vpm_int.h */
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2013.
+ */
+/* ====================================================================
+ * Copyright (c) 2013 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).
+ *
+ */
+
+/* internal only structure to hold additional X509_VERIFY_PARAM data */
+
+struct X509_VERIFY_PARAM_ID_st
+ {
+ unsigned char *host; /* If not NULL hostname to match */
+ size_t hostlen;
+ unsigned int hostflags; /* Flags to control matching features */
+ unsigned char *email; /* If not NULL email address to match */
+ size_t emaillen;
+ unsigned char *ip; /* If not NULL IP address to match */
+ size_t iplen; /* Length of IP address */
+ };
diff --git a/src/crypto/x509/x509.c b/src/crypto/x509/x509.c
new file mode 100644
index 0000000..31f9e1e
--- /dev/null
+++ b/src/crypto/x509/x509.c
@@ -0,0 +1,152 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <openssl/bio.h>
+#include <openssl/mem.h>
+
+
+int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
+ int ptype, void *pval, uint8_t *penc, int penclen) {
+ uint8_t **ppenc = NULL;
+ if (version >= 0) {
+ if (!ASN1_INTEGER_set(priv->version, version)) {
+ return 0;
+ }
+ }
+
+ if (penc) {
+ int pmtype;
+ ASN1_OCTET_STRING *oct;
+
+ oct = ASN1_OCTET_STRING_new();
+ if (!oct) {
+ return 0;
+ }
+ oct->data = penc;
+ ppenc = &oct->data;
+ oct->length = penclen;
+ if (priv->broken == PKCS8_NO_OCTET) {
+ pmtype = V_ASN1_SEQUENCE;
+ } else {
+ pmtype = V_ASN1_OCTET_STRING;
+ }
+ ASN1_TYPE_set(priv->pkey, pmtype, oct);
+ }
+
+ if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) {
+ /* If call fails do not swallow 'enc' */
+ if (ppenc) {
+ *ppenc = NULL;
+ }
+ return 0;
+ }
+
+ return 1;
+}
+
+int PKCS8_pkey_get0(ASN1_OBJECT **ppkalg, const uint8_t **pk, int *ppklen,
+ X509_ALGOR **pa, PKCS8_PRIV_KEY_INFO *p8) {
+ if (ppkalg) {
+ *ppkalg = p8->pkeyalg->algorithm;
+ }
+
+ if (p8->pkey->type == V_ASN1_OCTET_STRING) {
+ p8->broken = PKCS8_OK;
+ if (pk) {
+ *pk = p8->pkey->value.octet_string->data;
+ *ppklen = p8->pkey->value.octet_string->length;
+ }
+ } else if (p8->pkey->type == V_ASN1_SEQUENCE) {
+ p8->broken = PKCS8_NO_OCTET;
+ if (pk) {
+ *pk = p8->pkey->value.sequence->data;
+ *ppklen = p8->pkey->value.sequence->length;
+ }
+ } else {
+ return 0;
+ }
+
+ if (pa) {
+ *pa = p8->pkeyalg;
+ }
+ return 1;
+}
+
+int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) {
+ const uint8_t *s;
+ int i, n;
+
+ n = sig->length;
+ s = sig->data;
+ for (i = 0; i < n; i++) {
+ if ((i % 18) == 0) {
+ if (BIO_write(bp, "\n", 1) <= 0 ||
+ BIO_indent(bp, indent, indent) <= 0) {
+ return 0;
+ }
+ }
+ if (BIO_printf(bp, "%02x%s", s[i], ((i + 1) == n) ? "" : ":") <= 0) {
+ return 0;
+ }
+ }
+ if (BIO_write(bp, "\n", 1) != 1) {
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
new file mode 100644
index 0000000..3613c35
--- /dev/null
+++ b/src/crypto/x509/x509_att.c
@@ -0,0 +1,353 @@
+/* crypto/x509/x509_att.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
+{
+ return sk_X509_ATTRIBUTE_num(x);
+}
+
+int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
+ int lastpos)
+{
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509at_get_attr_by_OBJ(x,obj,lastpos));
+}
+
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj,
+ int lastpos)
+{
+ int n;
+ X509_ATTRIBUTE *ex;
+
+ if (sk == NULL) return(-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos=0;
+ n=sk_X509_ATTRIBUTE_num(sk);
+ for ( ; lastpos < n; lastpos++)
+ {
+ ex=sk_X509_ATTRIBUTE_value(sk,lastpos);
+ if (OBJ_cmp(ex->object,obj) == 0)
+ return(lastpos);
+ }
+ return(-1);
+}
+
+X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
+{
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
+ return NULL;
+ else
+ return sk_X509_ATTRIBUTE_value(x,loc);
+}
+
+X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
+{
+ X509_ATTRIBUTE *ret;
+
+ if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
+ return(NULL);
+ ret=sk_X509_ATTRIBUTE_delete(x,loc);
+ return(ret);
+}
+
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
+ X509_ATTRIBUTE *attr)
+{
+ X509_ATTRIBUTE *new_attr=NULL;
+ STACK_OF(X509_ATTRIBUTE) *sk=NULL;
+
+ if (x == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509at_add1_attr, ERR_R_PASSED_NULL_PARAMETER);
+ goto err2;
+ }
+
+ if (*x == NULL)
+ {
+ if ((sk=sk_X509_ATTRIBUTE_new_null()) == NULL)
+ goto err;
+ }
+ else
+ sk= *x;
+
+ if ((new_attr=X509_ATTRIBUTE_dup(attr)) == NULL)
+ goto err2;
+ if (!sk_X509_ATTRIBUTE_push(sk,new_attr))
+ goto err;
+ if (*x == NULL)
+ *x=sk;
+ return(sk);
+err:
+ OPENSSL_PUT_ERROR(X509, X509at_add1_attr, ERR_R_MALLOC_FAILURE);
+err2:
+ if (new_attr != NULL) X509_ATTRIBUTE_free(new_attr);
+ if (sk != NULL) sk_X509_ATTRIBUTE_free(sk);
+ return(NULL);
+}
+
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len)
+{
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
+ if(!attr) return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
+}
+
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
+ int nid, int type,
+ const unsigned char *bytes, int len)
+{
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
+ if(!attr) return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
+}
+
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len)
+{
+ X509_ATTRIBUTE *attr;
+ STACK_OF(X509_ATTRIBUTE) *ret;
+ attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
+ if(!attr) return 0;
+ ret = X509at_add1_attr(x, attr);
+ X509_ATTRIBUTE_free(attr);
+ return ret;
+}
+
+void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
+ ASN1_OBJECT *obj, int lastpos, int type)
+{
+ int i;
+ X509_ATTRIBUTE *at;
+ i = X509at_get_attr_by_OBJ(x, obj, lastpos);
+ if (i == -1)
+ return NULL;
+ if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
+ return NULL;
+ at = X509at_get_attr(x, i);
+ if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
+ return NULL;
+ return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
+}
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
+ int atrtype, const void *data, int len)
+{
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ return X509_ATTRIBUTE_create_by_OBJ(attr,obj,atrtype,data,len);
+}
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
+ const ASN1_OBJECT *obj, int atrtype, const void *data, int len)
+{
+ X509_ATTRIBUTE *ret;
+
+ if ((attr == NULL) || (*attr == NULL))
+ {
+ if ((ret=X509_ATTRIBUTE_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_OBJ, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+ }
+ else
+ ret= *attr;
+
+ if (!X509_ATTRIBUTE_set1_object(ret,obj))
+ goto err;
+ if (!X509_ATTRIBUTE_set1_data(ret,atrtype,data,len))
+ goto err;
+
+ if ((attr != NULL) && (*attr == NULL)) *attr=ret;
+ return(ret);
+err:
+ if ((attr == NULL) || (ret != *attr))
+ X509_ATTRIBUTE_free(ret);
+ return(NULL);
+}
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
+ const char *atrname, int type, const unsigned char *bytes, int len)
+ {
+ ASN1_OBJECT *obj;
+ X509_ATTRIBUTE *nattr;
+
+ obj=OBJ_txt2obj(atrname, 0);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_create_by_txt, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", atrname);
+ return(NULL);
+ }
+ nattr = X509_ATTRIBUTE_create_by_OBJ(attr,obj,type,bytes,len);
+ ASN1_OBJECT_free(obj);
+ return nattr;
+ }
+
+int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
+{
+ if ((attr == NULL) || (obj == NULL))
+ return(0);
+ ASN1_OBJECT_free(attr->object);
+ attr->object=OBJ_dup(obj);
+ return(1);
+}
+
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
+{
+ ASN1_TYPE *ttmp;
+ ASN1_STRING *stmp = NULL;
+ int atype = 0;
+ if (!attr) return 0;
+ if(attrtype & MBSTRING_FLAG) {
+ stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
+ OBJ_obj2nid(attr->object));
+ if(!stmp) {
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_set1_data, ERR_R_ASN1_LIB);
+ return 0;
+ }
+ atype = stmp->type;
+ } else if (len != -1){
+ if(!(stmp = ASN1_STRING_type_new(attrtype))) goto err;
+ if(!ASN1_STRING_set(stmp, data, len)) goto err;
+ atype = attrtype;
+ }
+ if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
+ attr->single = 0;
+ /* This is a bit naughty because the attribute should really have
+ * at least one value but some types use and zero length SET and
+ * require this.
+ */
+ if (attrtype == 0)
+ return 1;
+ if(!(ttmp = ASN1_TYPE_new())) goto err;
+ if ((len == -1) && !(attrtype & MBSTRING_FLAG))
+ {
+ if (!ASN1_TYPE_set1(ttmp, attrtype, data))
+ goto err;
+ }
+ else
+ ASN1_TYPE_set(ttmp, atype, stmp);
+ if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err;
+ return 1;
+ err:
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_set1_data, ERR_R_MALLOC_FAILURE);
+ return 0;
+}
+
+int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
+{
+ if(!attr->single) return sk_ASN1_TYPE_num(attr->value.set);
+ if(attr->value.single) return 1;
+ return 0;
+}
+
+ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
+{
+ if (attr == NULL) return(NULL);
+ return(attr->object);
+}
+
+void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
+ int atrtype, void *data)
+{
+ ASN1_TYPE *ttmp;
+ ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
+ if(!ttmp) return NULL;
+ if(atrtype != ASN1_TYPE_get(ttmp)){
+ OPENSSL_PUT_ERROR(X509, X509_ATTRIBUTE_get0_data, X509_R_WRONG_TYPE);
+ return NULL;
+ }
+ return ttmp->value.ptr;
+}
+
+ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
+{
+ if (attr == NULL) return(NULL);
+ if(idx >= X509_ATTRIBUTE_count(attr)) return NULL;
+ if(!attr->single) return sk_ASN1_TYPE_value(attr->value.set, idx);
+ else return attr->value.single;
+}
diff --git a/src/crypto/x509/x509_cmp.c b/src/crypto/x509/x509_cmp.c
new file mode 100644
index 0000000..712e36b
--- /dev/null
+++ b/src/crypto/x509/x509_cmp.c
@@ -0,0 +1,490 @@
+/* crypto/x509/x509_cmp.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
+ {
+ int i;
+ X509_CINF *ai,*bi;
+
+ ai=a->cert_info;
+ bi=b->cert_info;
+ i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
+ if (i) return(i);
+ return(X509_NAME_cmp(ai->issuer,bi->issuer));
+ }
+
+unsigned long X509_issuer_and_serial_hash(X509 *a)
+ {
+ unsigned long ret=0;
+ EVP_MD_CTX ctx;
+ unsigned char md[16];
+ char *f;
+
+ EVP_MD_CTX_init(&ctx);
+ f=X509_NAME_oneline(a->cert_info->issuer,NULL,0);
+ if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
+ goto err;
+ if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,strlen(f)))
+ goto err;
+ OPENSSL_free(f);
+ if(!EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data,
+ (unsigned long)a->cert_info->serialNumber->length))
+ goto err;
+ if (!EVP_DigestFinal_ex(&ctx,&(md[0]),NULL))
+ goto err;
+ ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
+ ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
+ )&0xffffffffL;
+ err:
+ EVP_MD_CTX_cleanup(&ctx);
+ return(ret);
+ }
+
+int X509_issuer_name_cmp(const X509 *a, const X509 *b)
+ {
+ return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer));
+ }
+
+int X509_subject_name_cmp(const X509 *a, const X509 *b)
+ {
+ return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
+ }
+
+int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
+ {
+ return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
+ }
+
+int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
+ {
+ return memcmp(a->sha1_hash, b->sha1_hash, 20);
+ }
+
+X509_NAME *X509_get_issuer_name(X509 *a)
+ {
+ return(a->cert_info->issuer);
+ }
+
+unsigned long X509_issuer_name_hash(X509 *x)
+ {
+ return(X509_NAME_hash(x->cert_info->issuer));
+ }
+
+unsigned long X509_issuer_name_hash_old(X509 *x)
+ {
+ return(X509_NAME_hash_old(x->cert_info->issuer));
+ }
+
+X509_NAME *X509_get_subject_name(X509 *a)
+ {
+ return(a->cert_info->subject);
+ }
+
+ASN1_INTEGER *X509_get_serialNumber(X509 *a)
+ {
+ return(a->cert_info->serialNumber);
+ }
+
+unsigned long X509_subject_name_hash(X509 *x)
+ {
+ return(X509_NAME_hash(x->cert_info->subject));
+ }
+
+unsigned long X509_subject_name_hash_old(X509 *x)
+ {
+ return(X509_NAME_hash_old(x->cert_info->subject));
+ }
+
+/* Compare two certificates: they must be identical for
+ * this to work. NB: Although "cmp" operations are generally
+ * prototyped to take "const" arguments (eg. for use in
+ * STACKs), the way X509 handling is - these operations may
+ * involve ensuring the hashes are up-to-date and ensuring
+ * certain cert information is cached. So this is the point
+ * where the "depth-first" constification tree has to halt
+ * with an evil cast.
+ */
+int X509_cmp(const X509 *a, const X509 *b)
+{
+ int rv;
+ /* ensure hash is valid */
+ X509_check_purpose((X509 *)a, -1, 0);
+ X509_check_purpose((X509 *)b, -1, 0);
+
+ rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+ if (rv)
+ return rv;
+ /* Check for match against stored encoding too */
+ if (!a->cert_info->enc.modified && !b->cert_info->enc.modified)
+ {
+ rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
+ if (rv)
+ return rv;
+ return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
+ a->cert_info->enc.len);
+ }
+ return rv;
+}
+
+
+int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
+ {
+ int ret;
+
+ /* Ensure canonical encoding is present and up to date */
+
+ if (!a->canon_enc || a->modified)
+ {
+ ret = i2d_X509_NAME((X509_NAME *)a, NULL);
+ if (ret < 0)
+ return -2;
+ }
+
+ if (!b->canon_enc || b->modified)
+ {
+ ret = i2d_X509_NAME((X509_NAME *)b, NULL);
+ if (ret < 0)
+ return -2;
+ }
+
+ ret = a->canon_enclen - b->canon_enclen;
+
+ if (ret)
+ return ret;
+
+ return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+
+ }
+
+unsigned long X509_NAME_hash(X509_NAME *x)
+ {
+ unsigned long ret=0;
+ unsigned char md[SHA_DIGEST_LENGTH];
+
+ /* Make sure X509_NAME structure contains valid cached encoding */
+ i2d_X509_NAME(x,NULL);
+ if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
+ NULL))
+ return 0;
+
+ ret=( ((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
+ ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
+ )&0xffffffffL;
+ return(ret);
+ }
+
+
+/* I now DER encode the name and hash it. Since I cache the DER encoding,
+ * this is reasonably efficient. */
+
+unsigned long X509_NAME_hash_old(X509_NAME *x)
+ {
+ EVP_MD_CTX md_ctx;
+ unsigned long ret=0;
+ unsigned char md[16];
+
+ /* Make sure X509_NAME structure contains valid cached encoding */
+ i2d_X509_NAME(x,NULL);
+ EVP_MD_CTX_init(&md_ctx);
+ /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
+ if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
+ && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
+ && EVP_DigestFinal_ex(&md_ctx,md,NULL))
+ ret=(((unsigned long)md[0] )|((unsigned long)md[1]<<8L)|
+ ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
+ )&0xffffffffL;
+ EVP_MD_CTX_cleanup(&md_ctx);
+
+ return(ret);
+ }
+
+/* Search a stack of X509 for a match */
+X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
+ ASN1_INTEGER *serial)
+ {
+ size_t i;
+ X509_CINF cinf;
+ X509 x,*x509=NULL;
+
+ if(!sk) return NULL;
+
+ x.cert_info= &cinf;
+ cinf.serialNumber=serial;
+ cinf.issuer=name;
+
+ for (i=0; i<sk_X509_num(sk); i++)
+ {
+ x509=sk_X509_value(sk,i);
+ if (X509_issuer_and_serial_cmp(x509,&x) == 0)
+ return(x509);
+ }
+ return(NULL);
+ }
+
+X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
+ {
+ X509 *x509;
+ size_t i;
+
+ for (i=0; i<sk_X509_num(sk); i++)
+ {
+ x509=sk_X509_value(sk,i);
+ if (X509_NAME_cmp(X509_get_subject_name(x509),name) == 0)
+ return(x509);
+ }
+ return(NULL);
+ }
+
+EVP_PKEY *X509_get_pubkey(X509 *x)
+ {
+ if ((x == NULL) || (x->cert_info == NULL))
+ return(NULL);
+ return(X509_PUBKEY_get(x->cert_info->key));
+ }
+
+ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
+ {
+ if(!x) return NULL;
+ return x->cert_info->key->public_key;
+ }
+
+
+int X509_check_private_key(X509 *x, EVP_PKEY *k)
+ {
+ EVP_PKEY *xk;
+ int ret;
+
+ xk=X509_get_pubkey(x);
+
+ if (xk)
+ ret = EVP_PKEY_cmp(xk, k);
+ else
+ ret = -2;
+
+ switch (ret)
+ {
+ case 1:
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ OPENSSL_PUT_ERROR(X509, X509_check_private_key, X509_R_UNKNOWN_KEY_TYPE);
+ }
+ if (xk)
+ EVP_PKEY_free(xk);
+ if (ret > 0)
+ return 1;
+ return 0;
+ }
+
+/* Check a suite B algorithm is permitted: pass in a public key and
+ * the NID of its signature (or 0 if no signature). The pflags is
+ * a pointer to a flags field which must contain the suite B verification
+ * flags.
+ */
+
+
+static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
+ {
+ const EC_GROUP *grp = NULL;
+ int curve_nid;
+ if (pkey && pkey->type == EVP_PKEY_EC)
+ grp = EC_KEY_get0_group(pkey->pkey.ec);
+ if (!grp)
+ return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
+ curve_nid = EC_GROUP_get_curve_name(grp);
+ /* Check curve is consistent with LOS */
+ if (curve_nid == NID_secp384r1) /* P-384 */
+ {
+ /* Check signature algorithm is consistent with
+ * curve.
+ */
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ /* If we encounter P-384 we cannot use P-256 later */
+ *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
+ }
+ else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */
+ {
+ if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
+ return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+ if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
+ return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+ }
+ else
+ return X509_V_ERR_SUITE_B_INVALID_CURVE;
+
+ return X509_V_OK;
+ }
+
+int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
+ unsigned long flags)
+ {
+ int rv, sign_nid;
+ size_t i;
+ EVP_PKEY *pk = NULL;
+ unsigned long tflags;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ tflags = flags;
+ /* If no EE certificate passed in must be first in chain */
+ if (x == NULL)
+ {
+ x = sk_X509_value(chain, 0);
+ i = 1;
+ }
+ else
+ i = 0;
+
+ if (X509_get_version(x) != 2)
+ {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+
+ pk = X509_get_pubkey(x);
+ /* Check EE key only */
+ rv = check_suite_b(pk, -1, &tflags);
+ if (rv != X509_V_OK)
+ {
+ /* Correct error depth */
+ i = 0;
+ goto end;
+ }
+ for(; i < sk_X509_num(chain); i++)
+ {
+ sign_nid = X509_get_signature_nid(x);
+ x = sk_X509_value(chain, i);
+ if (X509_get_version(x) != 2)
+ {
+ rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+ goto end;
+ }
+ EVP_PKEY_free(pk);
+ pk = X509_get_pubkey(x);
+ rv = check_suite_b(pk, sign_nid, &tflags);
+ if (rv != X509_V_OK)
+ goto end;
+ }
+
+ /* Final check: root CA signature */
+ rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
+ end:
+ if (pk)
+ EVP_PKEY_free(pk);
+ if (rv != X509_V_OK)
+ {
+ /* Invalid signature or LOS errors are for previous cert */
+ if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
+ || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
+ i--;
+ /* If we have LOS error and flags changed then we are signing
+ * P-384 with P-256. Use more meaninggul error.
+ */
+ if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
+ rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
+ if (perror_depth)
+ *perror_depth = i;
+ }
+ return rv;
+ }
+
+int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
+ {
+ int sign_nid;
+ if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+ return X509_V_OK;
+ sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
+ return check_suite_b(pk, sign_nid, &flags);
+ }
+
+/* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
+ * count but it has the same effect by duping the STACK and upping the ref
+ * of each X509 structure.
+ */
+STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
+ {
+ STACK_OF(X509) *ret;
+ size_t i;
+ ret = sk_X509_dup(chain);
+ for (i = 0; i < sk_X509_num(ret); i++)
+ {
+ X509_up_ref(sk_X509_value(ret, i));
+ }
+ return ret;
+ }
diff --git a/src/crypto/x509/x509_d2.c b/src/crypto/x509/x509_d2.c
new file mode 100644
index 0000000..2161d85
--- /dev/null
+++ b/src/crypto/x509/x509_d2.c
@@ -0,0 +1,105 @@
+/* crypto/x509/x509_d2.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/err.h>
+#include <openssl/x509.h>
+
+
+#ifndef OPENSSL_NO_STDIO
+int X509_STORE_set_default_paths(X509_STORE *ctx)
+ {
+ X509_LOOKUP *lookup;
+
+ lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
+ if (lookup == NULL) return(0);
+ X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
+
+ lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
+ if (lookup == NULL) return(0);
+ X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
+
+ /* clear any errors */
+ ERR_clear_error();
+
+ return(1);
+ }
+
+int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
+ const char *path)
+ {
+ X509_LOOKUP *lookup;
+
+ if (file != NULL)
+ {
+ lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
+ if (lookup == NULL) return(0);
+ if (X509_LOOKUP_load_file(lookup,file,X509_FILETYPE_PEM) != 1)
+ return(0);
+ }
+ if (path != NULL)
+ {
+ lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
+ if (lookup == NULL) return(0);
+ if (X509_LOOKUP_add_dir(lookup,path,X509_FILETYPE_PEM) != 1)
+ return(0);
+ }
+ if ((path == NULL) && (file == NULL))
+ return(0);
+ return(1);
+ }
+
+#endif
diff --git a/src/crypto/x509/x509_def.c b/src/crypto/x509/x509_def.c
new file mode 100644
index 0000000..dbae289
--- /dev/null
+++ b/src/crypto/x509/x509_def.c
@@ -0,0 +1,88 @@
+/* crypto/x509/x509_def.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+
+/* TODO(fork): cleanup */
+
+#define OPENSSLDIR "/etc/ssl"
+#define X509_CERT_AREA OPENSSLDIR
+#define X509_CERT_DIR OPENSSLDIR "/certs"
+#define X509_CERT_FILE OPENSSLDIR "/cert.pem"
+#define X509_PRIVATE_DIR OPENSSLDIR "/private"
+#define X509_CERT_DIR_EVP "SSL_CERT_DIR"
+#define X509_CERT_FILE_EVP "SSL_CERT_FILE"
+
+const char *X509_get_default_private_dir(void)
+ { return(X509_PRIVATE_DIR); }
+
+const char *X509_get_default_cert_area(void)
+ { return(X509_CERT_AREA); }
+
+const char *X509_get_default_cert_dir(void)
+ { return(X509_CERT_DIR); }
+
+const char *X509_get_default_cert_file(void)
+ { return(X509_CERT_FILE); }
+
+const char *X509_get_default_cert_dir_env(void)
+ { return(X509_CERT_DIR_EVP); }
+
+const char *X509_get_default_cert_file_env(void)
+ { return(X509_CERT_FILE_EVP); }
+
diff --git a/src/crypto/x509/x509_error.c b/src/crypto/x509/x509_error.c
new file mode 100644
index 0000000..222a40a
--- /dev/null
+++ b/src/crypto/x509/x509_error.c
@@ -0,0 +1,125 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/err.h>
+
+#include <openssl/x509.h>
+
+const ERR_STRING_DATA X509_error_string_data[] = {
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_digest, 0), "ASN1_digest"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_generate_v3, 0), "ASN1_generate_v3"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_sign_ctx, 0), "ASN1_item_sign_ctx"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_item_verify, 0), "ASN1_item_verify"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_ASN1_sign, 0), "ASN1_sign"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_decode, 0), "NETSCAPE_SPKI_b64_decode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_NETSCAPE_SPKI_b64_encode, 0), "NETSCAPE_SPKI_b64_encode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_PKCS7_get_certificates, 0), "PKCS7_get_certificates"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_NID, 0), "X509_ATTRIBUTE_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_OBJ, 0), "X509_ATTRIBUTE_create_by_OBJ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_create_by_txt, 0), "X509_ATTRIBUTE_create_by_txt"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_get0_data, 0), "X509_ATTRIBUTE_get0_data"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_ATTRIBUTE_set1_data, 0), "X509_ATTRIBUTE_set1_data"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_add0_revoked, 0), "X509_CRL_add0_revoked"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_diff, 0), "X509_CRL_diff"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_CRL_print_fp, 0), "X509_CRL_print_fp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_NID, 0), "X509_EXTENSION_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_EXTENSION_create_by_OBJ, 0), "X509_EXTENSION_create_by_OBJ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_INFO_new, 0), "X509_INFO_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_NID, 0), "X509_NAME_ENTRY_create_by_NID"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_create_by_txt, 0), "X509_NAME_ENTRY_create_by_txt"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_ENTRY_set_object, 0), "X509_NAME_ENTRY_set_object"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_add_entry, 0), "X509_NAME_add_entry"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_oneline, 0), "X509_NAME_oneline"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_NAME_print, 0), "X509_NAME_print"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PKEY_new, 0), "X509_PKEY_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_get, 0), "X509_PUBKEY_get"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_PUBKEY_set, 0), "X509_PUBKEY_set"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_check_private_key, 0), "X509_REQ_check_private_key"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_REQ_to_X509, 0), "X509_REQ_to_X509"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_get1_issuer, 0), "X509_STORE_CTX_get1_issuer"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_init, 0), "X509_STORE_CTX_init"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_new, 0), "X509_STORE_CTX_new"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_CTX_purpose_inherit, 0), "X509_STORE_CTX_purpose_inherit"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_cert, 0), "X509_STORE_add_cert"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_STORE_add_crl, 0), "X509_STORE_add_crl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_add, 0), "X509_TRUST_add"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_TRUST_set, 0), "X509_TRUST_set"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_check_private_key, 0), "X509_check_private_key"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_get_pubkey_parameters, 0), "X509_get_pubkey_parameters"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_crl_file, 0), "X509_load_cert_crl_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_cert_file, 0), "X509_load_cert_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_load_crl_file, 0), "X509_load_crl_file"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_print_ex_fp, 0), "X509_print_ex_fp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_to_X509_REQ, 0), "X509_to_X509_REQ"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509_verify_cert, 0), "X509_verify_cert"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509at_add1_attr, 0), "X509at_add1_attr"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_X509v3_add_ext, 0), "X509v3_add_ext"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_add_cert_dir, 0), "add_cert_dir"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_append_exp, 0), "append_exp"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_asn1_cb, 0), "asn1_cb"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_asn1_str2type, 0), "asn1_str2type"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_bitstr_cb, 0), "bitstr_cb"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_by_file_ctrl, 0), "by_file_ctrl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_check_policy, 0), "check_policy"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_d2i_X509_PKEY, 0), "d2i_X509_PKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_dir_ctrl, 0), "dir_ctrl"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_get_cert_by_subject, 0), "get_cert_by_subject"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_DSA_PUBKEY, 0), "i2d_DSA_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_EC_PUBKEY, 0), "i2d_EC_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_PrivateKey, 0), "i2d_PrivateKey"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_i2d_RSA_PUBKEY, 0), "i2d_RSA_PUBKEY"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_parse_tagging, 0), "parse_tagging"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_encode, 0), "x509_name_encode"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_d2i, 0), "x509_name_ex_d2i"},
+ {ERR_PACK(ERR_LIB_X509, X509_F_x509_name_ex_new, 0), "x509_name_ex_new"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_AKID_MISMATCH), "AKID_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_PKCS7_VERSION), "BAD_PKCS7_VERSION"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BAD_X509_FILETYPE), "BAD_X509_FILETYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_BASE64_DECODE_ERROR), "BASE64_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CANT_CHECK_DH_KEY), "CANT_CHECK_DH_KEY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CERT_ALREADY_IN_HASH_TABLE), "CERT_ALREADY_IN_HASH_TABLE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CONTEXT_NOT_INITIALISED), "CONTEXT_NOT_INITIALISED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_ALREADY_DELTA), "CRL_ALREADY_DELTA"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_CRL_VERIFY_FAILURE), "CRL_VERIFY_FAILURE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ERR_ASN1_LIB), "ERR_ASN1_LIB"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_IDP_MISMATCH), "IDP_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_BIT_STRING_BITS_LEFT), "INVALID_BIT_STRING_BITS_LEFT"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_DIRECTORY), "INVALID_DIRECTORY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_FIELD_NAME), "INVALID_FIELD_NAME"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_INVALID_TRUST), "INVALID_TRUST"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_ISSUER_MISMATCH), "ISSUER_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_TYPE_MISMATCH), "KEY_TYPE_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_KEY_VALUES_MISMATCH), "KEY_VALUES_MISMATCH"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_CERT_DIR), "LOADING_CERT_DIR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_LOADING_DEFAULTS), "LOADING_DEFAULTS"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_METHOD_NOT_SUPPORTED), "METHOD_NOT_SUPPORTED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NEWER_CRL_NOT_NEWER), "NEWER_CRL_NOT_NEWER"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NOT_PKCS7_SIGNED_DATA), "NOT_PKCS7_SIGNED_DATA"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERTIFICATES_INCLUDED), "NO_CERTIFICATES_INCLUDED"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY), "NO_CERT_SET_FOR_US_TO_VERIFY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_NO_CRL_NUMBER), "NO_CRL_NUMBER"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_DECODE_ERROR), "PUBLIC_KEY_DECODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_PUBLIC_KEY_ENCODE_ERROR), "PUBLIC_KEY_ENCODE_ERROR"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_SHOULD_RETRY), "SHOULD_RETRY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN), "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY), "UNABLE_TO_GET_CERTS_PUBLIC_KEY"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_KEY_TYPE), "UNKNOWN_KEY_TYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_NID), "UNKNOWN_NID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_PURPOSE_ID), "UNKNOWN_PURPOSE_ID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNKNOWN_TRUST_ID), "UNKNOWN_TRUST_ID"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_UNSUPPORTED_ALGORITHM), "UNSUPPORTED_ALGORITHM"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_LOOKUP_TYPE), "WRONG_LOOKUP_TYPE"},
+ {ERR_PACK(ERR_LIB_X509, 0, X509_R_WRONG_TYPE), "WRONG_TYPE"},
+ {0, NULL},
+};
diff --git a/src/crypto/x509/x509_ext.c b/src/crypto/x509/x509_ext.c
new file mode 100644
index 0000000..2f1e0c5
--- /dev/null
+++ b/src/crypto/x509/x509_ext.c
@@ -0,0 +1,206 @@
+/* crypto/x509/x509_ext.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+int X509_CRL_get_ext_count(X509_CRL *x)
+ {
+ return(X509v3_get_ext_count(x->crl->extensions));
+ }
+
+int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->crl->extensions,nid,lastpos));
+ }
+
+int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->crl->extensions,obj,lastpos));
+ }
+
+int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->crl->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc)
+ {
+ return(X509v3_get_ext(x->crl->extensions,loc));
+ }
+
+X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc)
+ {
+ return(X509v3_delete_ext(x->crl->extensions,loc));
+ }
+
+void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
+}
+
+int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
+ unsigned long flags)
+{
+ return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags);
+}
+
+int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->crl->extensions),ex,loc) != NULL);
+ }
+
+int X509_get_ext_count(X509 *x)
+ {
+ return(X509v3_get_ext_count(x->cert_info->extensions));
+ }
+
+int X509_get_ext_by_NID(X509 *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->cert_info->extensions,nid,lastpos));
+ }
+
+int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->cert_info->extensions,obj,lastpos));
+ }
+
+int X509_get_ext_by_critical(X509 *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->cert_info->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_get_ext(X509 *x, int loc)
+ {
+ return(X509v3_get_ext(x->cert_info->extensions,loc));
+ }
+
+X509_EXTENSION *X509_delete_ext(X509 *x, int loc)
+ {
+ return(X509v3_delete_ext(x->cert_info->extensions,loc));
+ }
+
+int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->cert_info->extensions),ex,loc) != NULL);
+ }
+
+void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
+}
+
+int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
+ unsigned long flags)
+{
+ return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit,
+ flags);
+}
+
+int X509_REVOKED_get_ext_count(X509_REVOKED *x)
+ {
+ return(X509v3_get_ext_count(x->extensions));
+ }
+
+int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos)
+ {
+ return(X509v3_get_ext_by_NID(x->extensions,nid,lastpos));
+ }
+
+int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj,
+ int lastpos)
+ {
+ return(X509v3_get_ext_by_OBJ(x->extensions,obj,lastpos));
+ }
+
+int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos)
+ {
+ return(X509v3_get_ext_by_critical(x->extensions,crit,lastpos));
+ }
+
+X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc)
+ {
+ return(X509v3_get_ext(x->extensions,loc));
+ }
+
+X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc)
+ {
+ return(X509v3_delete_ext(x->extensions,loc));
+ }
+
+int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc)
+ {
+ return(X509v3_add_ext(&(x->extensions),ex,loc) != NULL);
+ }
+
+void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx)
+{
+ return X509V3_get_d2i(x->extensions, nid, crit, idx);
+}
+
+int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
+ unsigned long flags)
+{
+ return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
+}
+
+IMPLEMENT_ASN1_SET_OF(X509_EXTENSION)
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
new file mode 100644
index 0000000..090d341
--- /dev/null
+++ b/src/crypto/x509/x509_lu.c
@@ -0,0 +1,740 @@
+/* crypto/x509/x509_lu.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
+ {
+ X509_LOOKUP *ret;
+
+ ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
+ if (ret == NULL) return NULL;
+
+ ret->init=0;
+ ret->skip=0;
+ ret->method=method;
+ ret->method_data=NULL;
+ ret->store_ctx=NULL;
+ if ((method->new_item != NULL) && !method->new_item(ret))
+ {
+ OPENSSL_free(ret);
+ return NULL;
+ }
+ return ret;
+ }
+
+void X509_LOOKUP_free(X509_LOOKUP *ctx)
+ {
+ if (ctx == NULL) return;
+ if ( (ctx->method != NULL) &&
+ (ctx->method->free != NULL))
+ (*ctx->method->free)(ctx);
+ OPENSSL_free(ctx);
+ }
+
+int X509_LOOKUP_init(X509_LOOKUP *ctx)
+ {
+ if (ctx->method == NULL) return 0;
+ if (ctx->method->init != NULL)
+ return ctx->method->init(ctx);
+ else
+ return 1;
+ }
+
+int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
+ {
+ if (ctx->method == NULL) return 0;
+ if (ctx->method->shutdown != NULL)
+ return ctx->method->shutdown(ctx);
+ else
+ return 1;
+ }
+
+int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
+ char **ret)
+ {
+ if (ctx->method == NULL) return -1;
+ if (ctx->method->ctrl != NULL)
+ return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
+ else
+ return 1;
+ }
+
+int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
+ return X509_LU_FAIL;
+ if (ctx->skip) return 0;
+ return ctx->method->get_by_subject(ctx,type,name,ret);
+ }
+
+int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
+ ASN1_INTEGER *serial, X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) ||
+ (ctx->method->get_by_issuer_serial == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
+ }
+
+int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
+ unsigned char *bytes, int len, X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
+ }
+
+int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
+ X509_OBJECT *ret)
+ {
+ if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
+ return X509_LU_FAIL;
+ return ctx->method->get_by_alias(ctx,type,str,len,ret);
+ }
+
+
+static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
+ {
+ int ret;
+
+ ret=((*a)->type - (*b)->type);
+ if (ret) return ret;
+ switch ((*a)->type)
+ {
+ case X509_LU_X509:
+ ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
+ break;
+ case X509_LU_CRL:
+ ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
+ break;
+ default:
+ /* abort(); */
+ return 0;
+ }
+ return ret;
+ }
+
+X509_STORE *X509_STORE_new(void)
+ {
+ X509_STORE *ret;
+
+ if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
+ return NULL;
+ memset(ret, 0, sizeof(*ret));
+ ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
+ ret->cache = 1;
+ ret->get_cert_methods = sk_X509_LOOKUP_new_null();
+
+ if ((ret->param = X509_VERIFY_PARAM_new()) == NULL)
+ goto err;
+
+ if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data))
+ goto err;
+
+ ret->references = 1;
+ return ret;
+err:
+ if (ret)
+ {
+ if (ret->param)
+ X509_VERIFY_PARAM_free(ret->param);
+ if (ret->get_cert_methods)
+ sk_X509_LOOKUP_free(ret->get_cert_methods);
+ if (ret->objs)
+ sk_X509_OBJECT_free(ret->objs);
+ OPENSSL_free(ret);
+ }
+ return NULL;
+ }
+
+static void cleanup(X509_OBJECT *a)
+ {
+ if (a->type == X509_LU_X509)
+ {
+ X509_free(a->data.x509);
+ }
+ else if (a->type == X509_LU_CRL)
+ {
+ X509_CRL_free(a->data.crl);
+ }
+ else
+ {
+ /* abort(); */
+ }
+
+ OPENSSL_free(a);
+ }
+
+void X509_STORE_free(X509_STORE *vfy)
+ {
+ int i;
+ size_t j;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ if (vfy == NULL)
+ return;
+
+ i=CRYPTO_add(&vfy->references,-1,CRYPTO_LOCK_X509_STORE);
+#ifdef REF_PRINT
+ REF_PRINT("X509_STORE",vfy);
+#endif
+ if (i > 0) return;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"X509_STORE_free, bad reference count\n");
+ abort(); /* ok */
+ }
+#endif
+
+ sk=vfy->get_cert_methods;
+ for (j=0; j<sk_X509_LOOKUP_num(sk); j++)
+ {
+ lu=sk_X509_LOOKUP_value(sk,j);
+ X509_LOOKUP_shutdown(lu);
+ X509_LOOKUP_free(lu);
+ }
+ sk_X509_LOOKUP_free(sk);
+ sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
+
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
+ if (vfy->param)
+ X509_VERIFY_PARAM_free(vfy->param);
+ OPENSSL_free(vfy);
+ }
+
+X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
+ {
+ size_t i;
+ STACK_OF(X509_LOOKUP) *sk;
+ X509_LOOKUP *lu;
+
+ sk=v->get_cert_methods;
+ for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
+ {
+ lu=sk_X509_LOOKUP_value(sk,i);
+ if (m == lu->method)
+ {
+ return lu;
+ }
+ }
+ /* a new one */
+ lu=X509_LOOKUP_new(m);
+ if (lu == NULL)
+ return NULL;
+ else
+ {
+ lu->store_ctx=v;
+ if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
+ return lu;
+ else
+ {
+ X509_LOOKUP_free(lu);
+ return NULL;
+ }
+ }
+ }
+
+int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
+ X509_OBJECT *ret)
+ {
+ X509_STORE *ctx=vs->ctx;
+ X509_LOOKUP *lu;
+ X509_OBJECT stmp,*tmp;
+ int i,j;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ if (tmp == NULL || type == X509_LU_CRL)
+ {
+ for (i=vs->current_method; i<(int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
+ {
+ lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
+ j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
+ if (j < 0)
+ {
+ vs->current_method=j;
+ return j;
+ }
+ else if (j)
+ {
+ tmp= &stmp;
+ break;
+ }
+ }
+ vs->current_method=0;
+ if (tmp == NULL)
+ return 0;
+ }
+
+/* if (ret->data.ptr != NULL)
+ X509_OBJECT_free_contents(ret); */
+
+ ret->type=tmp->type;
+ ret->data.ptr=tmp->data.ptr;
+
+ X509_OBJECT_up_ref_count(ret);
+
+ return 1;
+ }
+
+int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
+ {
+ X509_OBJECT *obj;
+ int ret=1;
+
+ if (x == NULL) return 0;
+ obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_cert, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type=X509_LU_X509;
+ obj->data.x509=x;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj))
+ {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_cert, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret=0;
+ }
+ else sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ return ret;
+ }
+
+int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
+ {
+ X509_OBJECT *obj;
+ int ret=1;
+
+ if (x == NULL) return 0;
+ obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_crl, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ obj->type=X509_LU_CRL;
+ obj->data.crl=x;
+
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+
+ X509_OBJECT_up_ref_count(obj);
+
+ if (X509_OBJECT_retrieve_match(ctx->objs, obj))
+ {
+ X509_OBJECT_free_contents(obj);
+ OPENSSL_free(obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_add_crl, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+ ret=0;
+ }
+ else sk_X509_OBJECT_push(ctx->objs, obj);
+
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+
+ return ret;
+ }
+
+void X509_OBJECT_up_ref_count(X509_OBJECT *a)
+ {
+ switch (a->type)
+ {
+ case X509_LU_X509:
+ X509_up_ref(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ CRYPTO_add(&a->data.crl->references,1,CRYPTO_LOCK_X509_CRL);
+ break;
+ }
+ }
+
+void X509_OBJECT_free_contents(X509_OBJECT *a)
+ {
+ switch (a->type)
+ {
+ case X509_LU_X509:
+ X509_free(a->data.x509);
+ break;
+ case X509_LU_CRL:
+ X509_CRL_free(a->data.crl);
+ break;
+ }
+ }
+
+static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name, int *pnmatch)
+ {
+ X509_OBJECT stmp;
+ X509 x509_s;
+ X509_CINF cinf_s;
+ X509_CRL crl_s;
+ X509_CRL_INFO crl_info_s;
+ size_t idx;
+
+ stmp.type=type;
+ switch (type)
+ {
+ case X509_LU_X509:
+ stmp.data.x509= &x509_s;
+ x509_s.cert_info= &cinf_s;
+ cinf_s.subject=name;
+ break;
+ case X509_LU_CRL:
+ stmp.data.crl= &crl_s;
+ crl_s.crl= &crl_info_s;
+ crl_info_s.issuer=name;
+ break;
+ default:
+ /* abort(); */
+ return -1;
+ }
+
+ idx = -1;
+ if (sk_X509_OBJECT_find(h, &idx, &stmp) && pnmatch)
+ {
+ int tidx;
+ const X509_OBJECT *tobj, *pstmp;
+ *pnmatch = 1;
+ pstmp = &stmp;
+ for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++)
+ {
+ tobj = sk_X509_OBJECT_value(h, tidx);
+ if (x509_object_cmp(&tobj, &pstmp))
+ break;
+ (*pnmatch)++;
+ }
+ }
+
+ return idx;
+ }
+
+
+int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name)
+ {
+ return x509_object_idx_cnt(h, type, name, NULL);
+ }
+
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
+ X509_NAME *name)
+ {
+ int idx;
+ idx = X509_OBJECT_idx_by_subject(h, type, name);
+ if (idx==-1) return NULL;
+ return sk_X509_OBJECT_value(h, idx);
+ }
+
+STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+ {
+ int i, idx, cnt;
+ STACK_OF(X509) *sk;
+ X509 *x;
+ X509_OBJECT *obj;
+ sk = sk_X509_new_null();
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+ if (idx < 0)
+ {
+ /* Nothing found in cache: do lookup to possibly add new
+ * objects to cache
+ */
+ X509_OBJECT xobj;
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj))
+ {
+ sk_X509_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_X509,nm, &cnt);
+ if (idx < 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ sk_X509_free(sk);
+ return NULL;
+ }
+ }
+ for (i = 0; i < cnt; i++, idx++)
+ {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.x509;
+ if (!sk_X509_push(sk, X509_up_ref(x)))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ X509_free(x);
+ sk_X509_pop_free(sk, X509_free);
+ return NULL;
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return sk;
+
+ }
+
+STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+ {
+ int i, idx, cnt;
+ STACK_OF(X509_CRL) *sk;
+ X509_CRL *x;
+ X509_OBJECT *obj, xobj;
+ sk = sk_X509_CRL_new_null();
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ /* Check cache first */
+ idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
+
+ /* Always do lookup to possibly add new CRLs to cache
+ */
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj))
+ {
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+ X509_OBJECT_free_contents(&xobj);
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_CRL, nm, &cnt);
+ if (idx < 0)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ sk_X509_CRL_free(sk);
+ return NULL;
+ }
+
+ for (i = 0; i < cnt; i++, idx++)
+ {
+ obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+ x = obj->data.crl;
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509_CRL);
+ if (!sk_X509_CRL_push(sk, x))
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ X509_CRL_free(x);
+ sk_X509_CRL_pop_free(sk, X509_CRL_free);
+ return NULL;
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return sk;
+ }
+
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
+ {
+ size_t idx, i;
+ X509_OBJECT *obj;
+
+ if (!sk_X509_OBJECT_find(h, &idx, x)) {
+ return NULL;
+ }
+ if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
+ return sk_X509_OBJECT_value(h, idx);
+ for (i = idx; i < sk_X509_OBJECT_num(h); i++)
+ {
+ obj = sk_X509_OBJECT_value(h, i);
+ if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
+ return NULL;
+ if (x->type == X509_LU_X509)
+ {
+ if (!X509_cmp(obj->data.x509, x->data.x509))
+ return obj;
+ }
+ else if (x->type == X509_LU_CRL)
+ {
+ if (!X509_CRL_match(obj->data.crl, x->data.crl))
+ return obj;
+ }
+ else
+ return obj;
+ }
+ return NULL;
+ }
+
+
+/* Try to get issuer certificate from store. Due to limitations
+ * of the API this can only retrieve a single certificate matching
+ * a given subject name. However it will fill the cache with all
+ * matching certificates, so we can examine the cache for all
+ * matches.
+ *
+ * Return values are:
+ * 1 lookup successful.
+ * 0 certificate not found.
+ * -1 some other error.
+ */
+int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
+ {
+ X509_NAME *xn;
+ X509_OBJECT obj, *pobj;
+ int ok, idx, ret;
+ size_t i;
+ xn=X509_get_issuer_name(x);
+ ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
+ if (ok != X509_LU_X509)
+ {
+ if (ok == X509_LU_RETRY)
+ {
+ X509_OBJECT_free_contents(&obj);
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_get1_issuer, X509_R_SHOULD_RETRY);
+ return -1;
+ }
+ else if (ok != X509_LU_FAIL)
+ {
+ X509_OBJECT_free_contents(&obj);
+ /* not good :-(, break anyway */
+ return -1;
+ }
+ return 0;
+ }
+ /* If certificate matches all OK */
+ if (ctx->check_issued(ctx, x, obj.data.x509))
+ {
+ *issuer = obj.data.x509;
+ return 1;
+ }
+ X509_OBJECT_free_contents(&obj);
+
+ /* Else find index of first cert accepted by 'check_issued' */
+ ret = 0;
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
+ idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
+ if (idx != -1) /* should be true as we've had at least one match */
+ {
+ /* Look through all matching certs for suitable issuer */
+ for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
+ {
+ pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
+ /* See if we've run past the matches */
+ if (pobj->type != X509_LU_X509)
+ break;
+ if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
+ break;
+ if (ctx->check_issued(ctx, x, pobj->data.x509))
+ {
+ *issuer = pobj->data.x509;
+ X509_OBJECT_up_ref_count(pobj);
+ ret = 1;
+ break;
+ }
+ }
+ }
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
+ return ret;
+ }
+
+int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
+ {
+ return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+ }
+
+int X509_STORE_set_depth(X509_STORE *ctx, int depth)
+ {
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+ return 1;
+ }
+
+int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
+ {
+ return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+ }
+
+int X509_STORE_set_trust(X509_STORE *ctx, int trust)
+ {
+ return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+ }
+
+int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
+ {
+ return X509_VERIFY_PARAM_set1(ctx->param, param);
+ }
+
+void X509_STORE_set_verify_cb(X509_STORE *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *))
+ {
+ ctx->verify_cb = verify_cb;
+ }
+
+void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
+ STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm))
+ {
+ ctx->lookup_crls = cb;
+ }
+
+X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
+ {
+ return ctx->ctx;
+ }
diff --git a/src/crypto/x509/x509_obj.c b/src/crypto/x509/x509_obj.c
new file mode 100644
index 0000000..914e0de
--- /dev/null
+++ b/src/crypto/x509/x509_obj.c
@@ -0,0 +1,191 @@
+/* crypto/x509/x509_obj.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
+ {
+ X509_NAME_ENTRY *ne;
+ size_t i;
+ int n,lold,l,l1,l2,num,j,type;
+ const char *s;
+ char *p;
+ unsigned char *q;
+ BUF_MEM *b=NULL;
+ static const char hex[17]="0123456789ABCDEF";
+ int gs_doit[4];
+ char tmp_buf[80];
+
+ if (buf == NULL)
+ {
+ if ((b=BUF_MEM_new()) == NULL) goto err;
+ if (!BUF_MEM_grow(b,200)) goto err;
+ b->data[0]='\0';
+ len=200;
+ }
+ if (a == NULL)
+ {
+ if(b)
+ {
+ buf=b->data;
+ OPENSSL_free(b);
+ }
+ strncpy(buf,"NO X509_NAME",len);
+ buf[len-1]='\0';
+ return buf;
+ }
+
+ len--; /* space for '\0' */
+ l=0;
+ for (i=0; i<sk_X509_NAME_ENTRY_num(a->entries); i++)
+ {
+ ne=sk_X509_NAME_ENTRY_value(a->entries,i);
+ n=OBJ_obj2nid(ne->object);
+ if ((n == NID_undef) || ((s=OBJ_nid2sn(n)) == NULL))
+ {
+ i2t_ASN1_OBJECT(tmp_buf,sizeof(tmp_buf),ne->object);
+ s=tmp_buf;
+ }
+ l1=strlen(s);
+
+ type=ne->value->type;
+ num=ne->value->length;
+ q=ne->value->data;
+
+ if ((type == V_ASN1_GENERALSTRING) && ((num%4) == 0))
+ {
+ gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=0;
+ for (j=0; j<num; j++)
+ if (q[j] != 0) gs_doit[j&3]=1;
+
+ if (gs_doit[0]|gs_doit[1]|gs_doit[2])
+ gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
+ else
+ {
+ gs_doit[0]=gs_doit[1]=gs_doit[2]=0;
+ gs_doit[3]=1;
+ }
+ }
+ else
+ gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
+
+ for (l2=j=0; j<num; j++)
+ {
+ if (!gs_doit[j&3]) continue;
+ l2++;
+ if ((q[j] < ' ') || (q[j] > '~')) l2+=3;
+ }
+
+ lold=l;
+ l+=1+l1+1+l2;
+ if (b != NULL)
+ {
+ if (!BUF_MEM_grow(b,l+1)) goto err;
+ p= &(b->data[lold]);
+ }
+ else if (l > len)
+ {
+ break;
+ }
+ else
+ p= &(buf[lold]);
+ *(p++)='/';
+ memcpy(p,s,(unsigned int)l1); p+=l1;
+ *(p++)='=';
+
+ q=ne->value->data;
+
+ for (j=0; j<num; j++)
+ {
+ if (!gs_doit[j&3]) continue;
+ n=q[j];
+ if ((n < ' ') || (n > '~'))
+ {
+ *(p++)='\\';
+ *(p++)='x';
+ *(p++)=hex[(n>>4)&0x0f];
+ *(p++)=hex[n&0x0f];
+ }
+ else
+ *(p++)=n;
+ }
+ *p='\0';
+ }
+ if (b != NULL)
+ {
+ p=b->data;
+ OPENSSL_free(b);
+ }
+ else
+ p=buf;
+ if (i == 0)
+ *p = '\0';
+ return(p);
+err:
+ OPENSSL_PUT_ERROR(X509, X509_NAME_oneline, ERR_R_MALLOC_FAILURE);
+ if (b != NULL) BUF_MEM_free(b);
+ return(NULL);
+ }
+
diff --git a/src/crypto/x509/x509_r2x.c b/src/crypto/x509/x509_r2x.c
new file mode 100644
index 0000000..3c8e9c0
--- /dev/null
+++ b/src/crypto/x509/x509_r2x.c
@@ -0,0 +1,113 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
+ {
+ X509 *ret=NULL;
+ X509_CINF *xi=NULL;
+ X509_NAME *xn;
+
+ if ((ret=X509_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_REQ_to_X509, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ /* duplicate the request */
+ xi=ret->cert_info;
+
+ if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0)
+ {
+ if ((xi->version=M_ASN1_INTEGER_new()) == NULL) goto err;
+ if (!ASN1_INTEGER_set(xi->version,2)) goto err;
+/* xi->extensions=ri->attributes; <- bad, should not ever be done
+ ri->attributes=NULL; */
+ }
+
+ xn=X509_REQ_get_subject_name(r);
+ if (X509_set_subject_name(ret,X509_NAME_dup(xn)) == 0)
+ goto err;
+ if (X509_set_issuer_name(ret,X509_NAME_dup(xn)) == 0)
+ goto err;
+
+ if (X509_gmtime_adj(xi->validity->notBefore,0) == NULL)
+ goto err;
+ if (X509_gmtime_adj(xi->validity->notAfter,(long)60*60*24*days) == NULL)
+ goto err;
+
+ X509_set_pubkey(ret,X509_REQ_get_pubkey(r));
+
+ if (!X509_sign(ret,pkey,EVP_md5()))
+ goto err;
+ if (0)
+ {
+err:
+ X509_free(ret);
+ ret=NULL;
+ }
+ return(ret);
+ }
+
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
new file mode 100644
index 0000000..daaedb6
--- /dev/null
+++ b/src/crypto/x509/x509_req.c
@@ -0,0 +1,313 @@
+/* crypto/x509/x509_req.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/pem.h>
+#include <openssl/x509.h>
+
+
+X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ X509_REQ *ret;
+ X509_REQ_INFO *ri;
+ int i;
+ EVP_PKEY *pktmp;
+
+ ret=X509_REQ_new();
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_to_X509_REQ, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ ri=ret->req_info;
+
+ ri->version->length=1;
+ ri->version->data=(unsigned char *)OPENSSL_malloc(1);
+ if (ri->version->data == NULL) goto err;
+ ri->version->data[0]=0; /* version == 0 */
+
+ if (!X509_REQ_set_subject_name(ret,X509_get_subject_name(x)))
+ goto err;
+
+ pktmp = X509_get_pubkey(x);
+ i=X509_REQ_set_pubkey(ret,pktmp);
+ EVP_PKEY_free(pktmp);
+ if (!i) goto err;
+
+ if (pkey != NULL)
+ {
+ if (!X509_REQ_sign(ret,pkey,md))
+ goto err;
+ }
+ return(ret);
+err:
+ X509_REQ_free(ret);
+ return(NULL);
+ }
+
+EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
+ {
+ if ((req == NULL) || (req->req_info == NULL))
+ return(NULL);
+ return(X509_PUBKEY_get(req->req_info->pubkey));
+ }
+
+int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
+ {
+ EVP_PKEY *xk=NULL;
+ int ok=0;
+
+ xk=X509_REQ_get_pubkey(x);
+ switch (EVP_PKEY_cmp(xk, k))
+ {
+ case 1:
+ ok=1;
+ break;
+ case 0:
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_KEY_VALUES_MISMATCH);
+ break;
+ case -1:
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_KEY_TYPE_MISMATCH);
+ break;
+ case -2:
+ if (k->type == EVP_PKEY_EC)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, ERR_R_EC_LIB);
+ break;
+ }
+ if (k->type == EVP_PKEY_DH)
+ {
+ /* No idea */
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_CANT_CHECK_DH_KEY);
+ break;
+ }
+ OPENSSL_PUT_ERROR(X509, X509_REQ_check_private_key, X509_R_UNKNOWN_KEY_TYPE);
+ }
+
+ EVP_PKEY_free(xk);
+ return(ok);
+ }
+
+/* It seems several organisations had the same idea of including a list of
+ * extensions in a certificate request. There are at least two OIDs that are
+ * used and there may be more: so the list is configurable.
+ */
+
+static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef};
+
+static const int *ext_nids = ext_nid_list;
+
+int X509_REQ_extension_nid(int req_nid)
+{
+ int i, nid;
+ for(i = 0; ; i++) {
+ nid = ext_nids[i];
+ if(nid == NID_undef) return 0;
+ else if (req_nid == nid) return 1;
+ }
+}
+
+const int *X509_REQ_get_extension_nids(void)
+{
+ return ext_nids;
+}
+
+void X509_REQ_set_extension_nids(const int *nids)
+{
+ ext_nids = nids;
+}
+
+STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
+ {
+ X509_ATTRIBUTE *attr;
+ ASN1_TYPE *ext = NULL;
+ int idx;
+ const int *pnid;
+ const unsigned char *p;
+
+ if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
+ return(NULL);
+ for (pnid = ext_nids; *pnid != NID_undef; pnid++)
+ {
+ idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
+ if (idx == -1)
+ continue;
+ attr = X509_REQ_get_attr(req, idx);
+ if(attr->single) ext = attr->value.single;
+ else if(sk_ASN1_TYPE_num(attr->value.set))
+ ext = sk_ASN1_TYPE_value(attr->value.set, 0);
+ break;
+ }
+ if(!ext || (ext->type != V_ASN1_SEQUENCE))
+ return NULL;
+ p = ext->value.sequence->data;
+ return (STACK_OF(X509_EXTENSION) *)
+ ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
+ ASN1_ITEM_rptr(X509_EXTENSIONS));
+}
+
+/* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
+ * in case we want to create a non standard one.
+ */
+
+int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
+ int nid)
+{
+ ASN1_TYPE *at = NULL;
+ X509_ATTRIBUTE *attr = NULL;
+ if(!(at = ASN1_TYPE_new()) ||
+ !(at->value.sequence = ASN1_STRING_new())) goto err;
+
+ at->type = V_ASN1_SEQUENCE;
+ /* Generate encoding of extensions */
+ at->value.sequence->length =
+ ASN1_item_i2d((ASN1_VALUE *)exts,
+ &at->value.sequence->data,
+ ASN1_ITEM_rptr(X509_EXTENSIONS));
+ if(!(attr = X509_ATTRIBUTE_new())) goto err;
+ if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
+ if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err;
+ at = NULL;
+ attr->single = 0;
+ attr->object = (ASN1_OBJECT*) OBJ_nid2obj(nid);
+ if (!req->req_info->attributes)
+ {
+ if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
+ goto err;
+ }
+ if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err;
+ return 1;
+ err:
+ X509_ATTRIBUTE_free(attr);
+ ASN1_TYPE_free(at);
+ return 0;
+}
+/* This is the normal usage: use the "official" OID */
+int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
+{
+ return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
+}
+
+/* Request attribute functions */
+
+int X509_REQ_get_attr_count(const X509_REQ *req)
+{
+ return X509at_get_attr_count(req->req_info->attributes);
+}
+
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
+ int lastpos)
+{
+ return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
+}
+
+int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
+ int lastpos)
+{
+ return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
+}
+
+X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
+{
+ return X509at_get_attr(req->req_info->attributes, loc);
+}
+
+X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
+{
+ return X509at_delete_attr(req->req_info->attributes, loc);
+}
+
+int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
+{
+ if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1;
+ return 0;
+}
+
+int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
+ const ASN1_OBJECT *obj, int type,
+ const unsigned char *bytes, int len)
+{
+ if(X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
+ type, bytes, len)) return 1;
+ return 0;
+}
+
+int X509_REQ_add1_attr_by_NID(X509_REQ *req,
+ int nid, int type,
+ const unsigned char *bytes, int len)
+{
+ if(X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
+ type, bytes, len)) return 1;
+ return 0;
+}
+
+int X509_REQ_add1_attr_by_txt(X509_REQ *req,
+ const char *attrname, int type,
+ const unsigned char *bytes, int len)
+{
+ if(X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
+ type, bytes, len)) return 1;
+ return 0;
+}
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
new file mode 100644
index 0000000..06658b0
--- /dev/null
+++ b/src/crypto/x509/x509_set.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/cipher.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_set_version(X509 *x, long version)
+ {
+ if (x == NULL) return(0);
+ if (version == 0)
+ {
+ M_ASN1_INTEGER_free(x->cert_info->version);
+ x->cert_info->version = NULL;
+ return(1);
+ }
+ if (x->cert_info->version == NULL)
+ {
+ if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL)
+ return(0);
+ }
+ return(ASN1_INTEGER_set(x->cert_info->version,version));
+ }
+
+int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
+ {
+ ASN1_INTEGER *in;
+
+ if (x == NULL) return(0);
+ in=x->cert_info->serialNumber;
+ if (in != serial)
+ {
+ in=M_ASN1_INTEGER_dup(serial);
+ if (in != NULL)
+ {
+ M_ASN1_INTEGER_free(x->cert_info->serialNumber);
+ x->cert_info->serialNumber=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_set_issuer_name(X509 *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_NAME_set(&x->cert_info->issuer,name));
+ }
+
+int X509_set_subject_name(X509 *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_NAME_set(&x->cert_info->subject,name));
+ }
+
+int X509_set_notBefore(X509 *x, const ASN1_TIME *tm)
+ {
+ ASN1_TIME *in;
+
+ if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
+ in=x->cert_info->validity->notBefore;
+ if (in != tm)
+ {
+ in=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->cert_info->validity->notBefore);
+ x->cert_info->validity->notBefore=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
+ {
+ ASN1_TIME *in;
+
+ if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
+ in=x->cert_info->validity->notAfter;
+ if (in != tm)
+ {
+ in=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->cert_info->validity->notAfter);
+ x->cert_info->validity->notAfter=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
+ {
+ if ((x == NULL) || (x->cert_info == NULL)) return(0);
+ return(X509_PUBKEY_set(&(x->cert_info->key),pkey));
+ }
+
+
+
diff --git a/src/crypto/x509/x509_trs.c b/src/crypto/x509/x509_trs.c
new file mode 100644
index 0000000..9b7cc9c
--- /dev/null
+++ b/src/crypto/x509/x509_trs.c
@@ -0,0 +1,304 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999. */
+/* ====================================================================
+ * Copyright (c) 1999 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 <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509v3.h>
+
+
+static int tr_cmp(const X509_TRUST **a,
+ const X509_TRUST **b);
+static void trtable_free(X509_TRUST *p);
+
+static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
+static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
+
+static int obj_trust(int id, X509 *x, int flags);
+static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
+
+/* WARNING: the following table should be kept in order of trust
+ * and without any gaps so we can just subtract the minimum trust
+ * value to get an index into the table
+ */
+
+static X509_TRUST trstandard[] = {
+{X509_TRUST_COMPAT, 0, trust_compat, (char *) "compatible", 0, NULL},
+{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *) "SSL Client", NID_client_auth, NULL},
+{X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *) "SSL Server", NID_server_auth, NULL},
+{X509_TRUST_EMAIL, 0, trust_1oidany, (char *) "S/MIME email", NID_email_protect, NULL},
+{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *) "Object Signer", NID_code_sign, NULL},
+{X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *) "OCSP responder", NID_OCSP_sign, NULL},
+{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *) "OCSP request", NID_ad_OCSP, NULL},
+{X509_TRUST_TSA, 0, trust_1oidany, (char *) "TSA server", NID_time_stamp, NULL}
+};
+
+#define X509_TRUST_COUNT (sizeof(trstandard)/sizeof(X509_TRUST))
+
+static STACK_OF(X509_TRUST) *trtable = NULL;
+
+static int tr_cmp(const X509_TRUST **a,
+ const X509_TRUST **b)
+{
+ return (*a)->trust - (*b)->trust;
+}
+
+int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int)
+{
+ int (*oldtrust)(int , X509 *, int);
+ oldtrust = default_trust;
+ default_trust = trust;
+ return oldtrust;
+}
+
+
+int X509_check_trust(X509 *x, int id, int flags)
+{
+ X509_TRUST *pt;
+ int idx;
+ if(id == -1) return 1;
+ /* We get this as a default value */
+ if (id == 0)
+ {
+ int rv;
+ rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
+ if (rv != X509_TRUST_UNTRUSTED)
+ return rv;
+ return trust_compat(NULL, x, 0);
+ }
+ idx = X509_TRUST_get_by_id(id);
+ if(idx == -1) return default_trust(id, x, flags);
+ pt = X509_TRUST_get0(idx);
+ return pt->check_trust(pt, x, flags);
+}
+
+int X509_TRUST_get_count(void)
+{
+ if(!trtable) return X509_TRUST_COUNT;
+ return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
+}
+
+X509_TRUST * X509_TRUST_get0(int idx)
+{
+ if(idx < 0) return NULL;
+ if(idx < (int)X509_TRUST_COUNT) return trstandard + idx;
+ return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
+}
+
+int X509_TRUST_get_by_id(int id)
+{
+ X509_TRUST tmp;
+ size_t idx;
+
+ if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
+ return id - X509_TRUST_MIN;
+ tmp.trust = id;
+ if(!trtable) return -1;
+ if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
+ return -1;
+ }
+ return idx + X509_TRUST_COUNT;
+}
+
+int X509_TRUST_set(int *t, int trust)
+{
+ if(X509_TRUST_get_by_id(trust) == -1) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_set, X509_R_INVALID_TRUST);
+ return 0;
+ }
+ *t = trust;
+ return 1;
+}
+
+int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
+ char *name, int arg1, void *arg2)
+{
+ int idx;
+ X509_TRUST *trtmp;
+ char *name_dup;
+
+ /* This is set according to what we change: application can't set it */
+ flags &= ~X509_TRUST_DYNAMIC;
+ /* This will always be set for application modified trust entries */
+ flags |= X509_TRUST_DYNAMIC_NAME;
+ /* Get existing entry if any */
+ idx = X509_TRUST_get_by_id(id);
+ /* Need a new entry */
+ if(idx == -1) {
+ if(!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ trtmp->flags = X509_TRUST_DYNAMIC;
+ } else trtmp = X509_TRUST_get0(idx);
+
+ /* Duplicate the supplied name. */
+ name_dup = BUF_strdup(name);
+ if (name_dup == NULL) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ if (idx == -1)
+ OPENSSL_free(trtmp);
+ return 0;
+ }
+
+ /* OPENSSL_free existing name if dynamic */
+ if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name);
+ trtmp->name = name_dup;
+ /* Keep the dynamic flag of existing entry */
+ trtmp->flags &= X509_TRUST_DYNAMIC;
+ /* Set all other flags */
+ trtmp->flags |= flags;
+
+ trtmp->trust = id;
+ trtmp->check_trust = ck;
+ trtmp->arg1 = arg1;
+ trtmp->arg2 = arg2;
+
+ /* If its a new entry manage the dynamic table */
+ if(idx == -1) {
+ if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ if (!sk_X509_TRUST_push(trtable, trtmp)) {
+ OPENSSL_PUT_ERROR(X509, X509_TRUST_add, ERR_R_MALLOC_FAILURE);
+ trtable_free(trtmp);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static void trtable_free(X509_TRUST *p)
+ {
+ if(!p) return;
+ if (p->flags & X509_TRUST_DYNAMIC)
+ {
+ if (p->flags & X509_TRUST_DYNAMIC_NAME)
+ OPENSSL_free(p->name);
+ OPENSSL_free(p);
+ }
+ }
+
+void X509_TRUST_cleanup(void)
+{
+ unsigned int i;
+ for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i);
+ sk_X509_TRUST_pop_free(trtable, trtable_free);
+ trtable = NULL;
+}
+
+int X509_TRUST_get_flags(X509_TRUST *xp)
+{
+ return xp->flags;
+}
+
+char *X509_TRUST_get0_name(X509_TRUST *xp)
+{
+ return xp->name;
+}
+
+int X509_TRUST_get_trust(X509_TRUST *xp)
+{
+ return xp->trust;
+}
+
+static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
+{
+ if(x->aux && (x->aux->trust || x->aux->reject))
+ return obj_trust(trust->arg1, x, flags);
+ /* we don't have any trust settings: for compatibility
+ * we return trusted if it is self signed
+ */
+ return trust_compat(trust, x, flags);
+}
+
+static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
+{
+ if(x->aux) return obj_trust(trust->arg1, x, flags);
+ return X509_TRUST_UNTRUSTED;
+}
+
+static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
+{
+ X509_check_purpose(x, -1, 0);
+ if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED;
+ else return X509_TRUST_UNTRUSTED;
+}
+
+static int obj_trust(int id, X509 *x, int flags)
+{
+ ASN1_OBJECT *obj;
+ size_t i;
+ X509_CERT_AUX *ax;
+ ax = x->aux;
+ if(!ax) return X509_TRUST_UNTRUSTED;
+ if(ax->reject) {
+ for(i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
+ obj = sk_ASN1_OBJECT_value(ax->reject, i);
+ if(OBJ_obj2nid(obj) == id) return X509_TRUST_REJECTED;
+ }
+ }
+ if(ax->trust) {
+ for(i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
+ obj = sk_ASN1_OBJECT_value(ax->trust, i);
+ if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED;
+ }
+ }
+ return X509_TRUST_UNTRUSTED;
+}
+
diff --git a/src/crypto/x509/x509_txt.c b/src/crypto/x509/x509_txt.c
new file mode 100644
index 0000000..c286710
--- /dev/null
+++ b/src/crypto/x509/x509_txt.c
@@ -0,0 +1,209 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/cipher.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+const char *X509_verify_cert_error_string(long n)
+ {
+ static char buf[100];
+
+ switch ((int)n)
+ {
+ case X509_V_OK:
+ return("ok");
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ return("unable to get issuer certificate");
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ return("unable to get certificate CRL");
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+ return("unable to decrypt certificate's signature");
+ case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+ return("unable to decrypt CRL's signature");
+ case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+ return("unable to decode issuer public key");
+ case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+ return("certificate signature failure");
+ case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+ return("CRL signature failure");
+ case X509_V_ERR_CERT_NOT_YET_VALID:
+ return("certificate is not yet valid");
+ case X509_V_ERR_CRL_NOT_YET_VALID:
+ return("CRL is not yet valid");
+ case X509_V_ERR_CERT_HAS_EXPIRED:
+ return("certificate has expired");
+ case X509_V_ERR_CRL_HAS_EXPIRED:
+ return("CRL has expired");
+ case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+ return("format error in certificate's notBefore field");
+ case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+ return("format error in certificate's notAfter field");
+ case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+ return("format error in CRL's lastUpdate field");
+ case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+ return("format error in CRL's nextUpdate field");
+ case X509_V_ERR_OUT_OF_MEM:
+ return("out of memory");
+ case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+ return("self signed certificate");
+ case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+ return("self signed certificate in certificate chain");
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ return("unable to get local issuer certificate");
+ case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+ return("unable to verify the first certificate");
+ case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+ return("certificate chain too long");
+ case X509_V_ERR_CERT_REVOKED:
+ return("certificate revoked");
+ case X509_V_ERR_INVALID_CA:
+ return ("invalid CA certificate");
+ case X509_V_ERR_INVALID_NON_CA:
+ return ("invalid non-CA certificate (has CA markings)");
+ case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+ return ("path length constraint exceeded");
+ case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
+ return("proxy path length constraint exceeded");
+ case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
+ return("proxy certificates not allowed, please set the appropriate flag");
+ case X509_V_ERR_INVALID_PURPOSE:
+ return ("unsupported certificate purpose");
+ case X509_V_ERR_CERT_UNTRUSTED:
+ return ("certificate not trusted");
+ case X509_V_ERR_CERT_REJECTED:
+ return ("certificate rejected");
+ case X509_V_ERR_APPLICATION_VERIFICATION:
+ return("application verification failure");
+ case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
+ return("subject issuer mismatch");
+ case X509_V_ERR_AKID_SKID_MISMATCH:
+ return("authority and subject key identifier mismatch");
+ case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+ return("authority and issuer serial number mismatch");
+ case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+ return("key usage does not include certificate signing");
+ case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+ return("unable to get CRL issuer certificate");
+ case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+ return("unhandled critical extension");
+ case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
+ return("key usage does not include CRL signing");
+ case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
+ return("key usage does not include digital signature");
+ case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
+ return("unhandled critical CRL extension");
+ case X509_V_ERR_INVALID_EXTENSION:
+ return("invalid or inconsistent certificate extension");
+ case X509_V_ERR_INVALID_POLICY_EXTENSION:
+ return("invalid or inconsistent certificate policy extension");
+ case X509_V_ERR_NO_EXPLICIT_POLICY:
+ return("no explicit policy");
+ case X509_V_ERR_DIFFERENT_CRL_SCOPE:
+ return("Different CRL scope");
+ case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
+ return("Unsupported extension feature");
+ case X509_V_ERR_UNNESTED_RESOURCE:
+ return("RFC 3779 resource not subset of parent's resources");
+
+ case X509_V_ERR_PERMITTED_VIOLATION:
+ return("permitted subtree violation");
+ case X509_V_ERR_EXCLUDED_VIOLATION:
+ return("excluded subtree violation");
+ case X509_V_ERR_SUBTREE_MINMAX:
+ return("name constraints minimum and maximum not supported");
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+ return("unsupported name constraint type");
+ case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+ return("unsupported or invalid name constraint syntax");
+ case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
+ return("unsupported or invalid name syntax");
+ case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
+ return("CRL path validation error");
+
+ case X509_V_ERR_SUITE_B_INVALID_VERSION:
+ return("Suite B: certificate version invalid");
+ case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
+ return("Suite B: invalid public key algorithm");
+ case X509_V_ERR_SUITE_B_INVALID_CURVE:
+ return("Suite B: invalid ECC curve");
+ case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
+ return("Suite B: invalid signature algorithm");
+ case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
+ return("Suite B: curve not allowed for this LOS");
+ case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
+ return("Suite B: cannot sign P-384 with P-256");
+
+ case X509_V_ERR_HOSTNAME_MISMATCH:
+ return("Hostname mismatch");
+ case X509_V_ERR_EMAIL_MISMATCH:
+ return("Email address mismatch");
+ case X509_V_ERR_IP_ADDRESS_MISMATCH:
+ return("IP address mismatch");
+
+ default:
+ BIO_snprintf(buf,sizeof buf,"error number %ld",n);
+ return(buf);
+ }
+ }
+
+
diff --git a/src/crypto/x509/x509_v3.c b/src/crypto/x509/x509_v3.c
new file mode 100644
index 0000000..95fe729
--- /dev/null
+++ b/src/crypto/x509/x509_v3.c
@@ -0,0 +1,271 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
+ {
+ if (x == NULL) return(0);
+ return(sk_X509_EXTENSION_num(x));
+ }
+
+int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
+ int lastpos)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509v3_get_ext_by_OBJ(x,obj,lastpos));
+ }
+
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, const ASN1_OBJECT *obj,
+ int lastpos)
+ {
+ int n;
+ X509_EXTENSION *ex;
+
+ if (sk == NULL) return(-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos=0;
+ n=sk_X509_EXTENSION_num(sk);
+ for ( ; lastpos < n; lastpos++)
+ {
+ ex=sk_X509_EXTENSION_value(sk,lastpos);
+ if (OBJ_cmp(ex->object,obj) == 0)
+ return(lastpos);
+ }
+ return(-1);
+ }
+
+int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit,
+ int lastpos)
+ {
+ int n;
+ X509_EXTENSION *ex;
+
+ if (sk == NULL) return(-1);
+ lastpos++;
+ if (lastpos < 0)
+ lastpos=0;
+ n=sk_X509_EXTENSION_num(sk);
+ for ( ; lastpos < n; lastpos++)
+ {
+ ex=sk_X509_EXTENSION_value(sk,lastpos);
+ if ( ((ex->critical > 0) && crit) ||
+ ((ex->critical <= 0) && !crit))
+ return(lastpos);
+ }
+ return(-1);
+ }
+
+X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
+ {
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
+ return NULL;
+ else
+ return sk_X509_EXTENSION_value(x,loc);
+ }
+
+X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
+ {
+ X509_EXTENSION *ret;
+
+ if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
+ return(NULL);
+ ret=sk_X509_EXTENSION_delete(x,loc);
+ return(ret);
+ }
+
+STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
+ X509_EXTENSION *ex, int loc)
+ {
+ X509_EXTENSION *new_ex=NULL;
+ int n;
+ STACK_OF(X509_EXTENSION) *sk=NULL;
+
+ if (x == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509v3_add_ext, ERR_R_PASSED_NULL_PARAMETER);
+ goto err2;
+ }
+
+ if (*x == NULL)
+ {
+ if ((sk=sk_X509_EXTENSION_new_null()) == NULL)
+ goto err;
+ }
+ else
+ sk= *x;
+
+ n=sk_X509_EXTENSION_num(sk);
+ if (loc > n) loc=n;
+ else if (loc < 0) loc=n;
+
+ if ((new_ex=X509_EXTENSION_dup(ex)) == NULL)
+ goto err2;
+ if (!sk_X509_EXTENSION_insert(sk,new_ex,loc))
+ goto err;
+ if (*x == NULL)
+ *x=sk;
+ return(sk);
+err:
+ OPENSSL_PUT_ERROR(X509, X509v3_add_ext, ERR_R_MALLOC_FAILURE);
+err2:
+ if (new_ex != NULL) X509_EXTENSION_free(new_ex);
+ if (sk != NULL) sk_X509_EXTENSION_free(sk);
+ return(NULL);
+ }
+
+X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
+ int crit, ASN1_OCTET_STRING *data)
+ {
+ const ASN1_OBJECT *obj;
+ X509_EXTENSION *ret;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_EXTENSION_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ ret=X509_EXTENSION_create_by_OBJ(ex,obj,crit,data);
+ return(ret);
+ }
+
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
+ const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data)
+ {
+ X509_EXTENSION *ret;
+
+ if ((ex == NULL) || (*ex == NULL))
+ {
+ if ((ret=X509_EXTENSION_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_EXTENSION_create_by_OBJ, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+ }
+ else
+ ret= *ex;
+
+ if (!X509_EXTENSION_set_object(ret,obj))
+ goto err;
+ if (!X509_EXTENSION_set_critical(ret,crit))
+ goto err;
+ if (!X509_EXTENSION_set_data(ret,data))
+ goto err;
+
+ if ((ex != NULL) && (*ex == NULL)) *ex=ret;
+ return(ret);
+err:
+ if ((ex == NULL) || (ret != *ex))
+ X509_EXTENSION_free(ret);
+ return(NULL);
+ }
+
+int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
+ {
+ if ((ex == NULL) || (obj == NULL))
+ return(0);
+ ASN1_OBJECT_free(ex->object);
+ ex->object=OBJ_dup(obj);
+ return(1);
+ }
+
+int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
+ {
+ if (ex == NULL) return(0);
+ ex->critical=(crit)?0xFF:-1;
+ return(1);
+ }
+
+int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
+ {
+ int i;
+
+ if (ex == NULL) return(0);
+ i=M_ASN1_OCTET_STRING_set(ex->value,data->data,data->length);
+ if (!i) return(0);
+ return(1);
+ }
+
+ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(NULL);
+ return(ex->object);
+ }
+
+ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(NULL);
+ return(ex->value);
+ }
+
+int X509_EXTENSION_get_critical(X509_EXTENSION *ex)
+ {
+ if (ex == NULL) return(0);
+ if(ex->critical > 0) return 1;
+ return 0;
+ }
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
new file mode 100644
index 0000000..285bcaf
--- /dev/null
+++ b/src/crypto/x509/x509_vfy.c
@@ -0,0 +1,2447 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+#include <time.h>
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "vpm_int.h"
+
+/* CRL score values */
+
+/* No unhandled critical extensions */
+
+#define CRL_SCORE_NOCRITICAL 0x100
+
+/* certificate is within CRL scope */
+
+#define CRL_SCORE_SCOPE 0x080
+
+/* CRL times valid */
+
+#define CRL_SCORE_TIME 0x040
+
+/* Issuer name matches certificate */
+
+#define CRL_SCORE_ISSUER_NAME 0x020
+
+/* If this score or above CRL is probably valid */
+
+#define CRL_SCORE_VALID (CRL_SCORE_NOCRITICAL|CRL_SCORE_TIME|CRL_SCORE_SCOPE)
+
+/* CRL issuer is certificate issuer */
+
+#define CRL_SCORE_ISSUER_CERT 0x018
+
+/* CRL issuer is on certificate path */
+
+#define CRL_SCORE_SAME_PATH 0x008
+
+/* CRL issuer matches CRL AKID */
+
+#define CRL_SCORE_AKID 0x004
+
+/* Have a delta CRL with valid times */
+
+#define CRL_SCORE_TIME_DELTA 0x002
+
+static int null_callback(int ok,X509_STORE_CTX *e);
+static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
+static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
+static int check_chain_extensions(X509_STORE_CTX *ctx);
+static int check_name_constraints(X509_STORE_CTX *ctx);
+static int check_id(X509_STORE_CTX *ctx);
+static int check_trust(X509_STORE_CTX *ctx);
+static int check_revocation(X509_STORE_CTX *ctx);
+static int check_cert(X509_STORE_CTX *ctx);
+static int check_policy(X509_STORE_CTX *ctx);
+
+static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
+ unsigned int *preasons,
+ X509_CRL *crl, X509 *x);
+static int get_crl_delta(X509_STORE_CTX *ctx,
+ X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
+static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score,
+ X509_CRL *base, STACK_OF(X509_CRL) *crls);
+static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
+ X509 **pissuer, int *pcrl_score);
+static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
+ unsigned int *preasons);
+static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
+static int check_crl_chain(X509_STORE_CTX *ctx,
+ STACK_OF(X509) *cert_path,
+ STACK_OF(X509) *crl_path);
+
+static int internal_verify(X509_STORE_CTX *ctx);
+const char X509_version[]="X.509";
+
+
+static int null_callback(int ok, X509_STORE_CTX *e)
+ {
+ return ok;
+ }
+
+#if 0
+static int x509_subject_cmp(X509 **a, X509 **b)
+ {
+ return X509_subject_name_cmp(*a,*b);
+ }
+#endif
+/* Return 1 is a certificate is self signed */
+static int cert_self_signed(X509 *x)
+ {
+ X509_check_purpose(x, -1, 0);
+ if (x->ex_flags & EXFLAG_SS)
+ return 1;
+ else
+ return 0;
+ }
+
+/* Given a certificate try and find an exact match in the store */
+
+static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
+ {
+ STACK_OF(X509) *certs;
+ X509 *xtmp = NULL;
+ size_t i;
+ /* Lookup all certs with matching subject name */
+ certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
+ if (certs == NULL)
+ return NULL;
+ /* Look for exact match */
+ for (i = 0; i < sk_X509_num(certs); i++)
+ {
+ xtmp = sk_X509_value(certs, i);
+ if (!X509_cmp(xtmp, x))
+ break;
+ }
+ if (i < sk_X509_num(certs))
+ X509_up_ref(xtmp);
+ else
+ xtmp = NULL;
+ sk_X509_pop_free(certs, X509_free);
+ return xtmp;
+ }
+
+int X509_verify_cert(X509_STORE_CTX *ctx)
+ {
+ X509 *x,*xtmp,*chain_ss=NULL;
+ int bad_chain = 0;
+ X509_VERIFY_PARAM *param = ctx->param;
+ int depth,i,ok=0;
+ int num;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+ STACK_OF(X509) *sktmp=NULL;
+ if (ctx->cert == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+ return -1;
+ }
+
+ cb=ctx->verify_cb;
+
+ /* first we make sure the chain we are going to build is
+ * present and that the first entry is in place */
+ if (ctx->chain == NULL)
+ {
+ if ( ((ctx->chain=sk_X509_new_null()) == NULL) ||
+ (!sk_X509_push(ctx->chain,ctx->cert)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ X509_up_ref(ctx->cert);
+ ctx->last_untrusted=1;
+ }
+
+ /* We use a temporary STACK so we can chop and hack at it */
+ if (ctx->untrusted != NULL
+ && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ num=sk_X509_num(ctx->chain);
+ x=sk_X509_value(ctx->chain,num-1);
+ depth=param->depth;
+
+
+ for (;;)
+ {
+ /* If we have enough, we break */
+ if (depth < num) break; /* FIXME: If this happens, we should take
+ * note of it and, if appropriate, use the
+ * X509_V_ERR_CERT_CHAIN_TOO_LONG error
+ * code later.
+ */
+
+ /* If we are self signed, we break */
+ if (cert_self_signed(x))
+ break;
+ /* If asked see if we can find issuer in trusted store first */
+ if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
+ {
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+ if (ok < 0)
+ return ok;
+ /* If successful for now free up cert so it
+ * will be picked up again later.
+ */
+ if (ok > 0)
+ {
+ X509_free(xtmp);
+ break;
+ }
+ }
+
+ /* If we were passed a cert chain, use it first */
+ if (ctx->untrusted != NULL)
+ {
+ xtmp=find_issuer(ctx, sktmp,x);
+ if (xtmp != NULL)
+ {
+ if (!sk_X509_push(ctx->chain,xtmp))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+ CRYPTO_add(&xtmp->references,1,CRYPTO_LOCK_X509);
+ (void)sk_X509_delete_ptr(sktmp,xtmp);
+ ctx->last_untrusted++;
+ x=xtmp;
+ num++;
+ /* reparse the full chain for
+ * the next one */
+ continue;
+ }
+ }
+ break;
+ }
+
+ /* at this point, chain should contain a list of untrusted
+ * certificates. We now need to add at least one trusted one,
+ * if possible, otherwise we complain. */
+
+ /* Examine last certificate in chain and see if it
+ * is self signed.
+ */
+
+ i=sk_X509_num(ctx->chain);
+ x=sk_X509_value(ctx->chain,i-1);
+ if (cert_self_signed(x))
+ {
+ /* we have a self signed certificate */
+ if (sk_X509_num(ctx->chain) == 1)
+ {
+ /* We have a single self signed certificate: see if
+ * we can find it in the store. We must have an exact
+ * match to avoid possible impersonation.
+ */
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+ if ((ok <= 0) || X509_cmp(x, xtmp))
+ {
+ ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+ ctx->current_cert=x;
+ ctx->error_depth=i-1;
+ if (ok == 1) X509_free(xtmp);
+ bad_chain = 1;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ else
+ {
+ /* We have a match: replace certificate with store version
+ * so we get any trust settings.
+ */
+ X509_free(x);
+ x = xtmp;
+ (void)sk_X509_set(ctx->chain, i - 1, x);
+ ctx->last_untrusted=0;
+ }
+ }
+ else
+ {
+ /* extract and save self signed certificate for later use */
+ chain_ss=sk_X509_pop(ctx->chain);
+ ctx->last_untrusted--;
+ num--;
+ x=sk_X509_value(ctx->chain,num-1);
+ }
+ }
+
+ /* We now lookup certs from the certificate store */
+ for (;;)
+ {
+ /* If we have enough, we break */
+ if (depth < num) break;
+
+ /* If we are self signed, we break */
+ if (cert_self_signed(x))
+ break;
+
+ ok = ctx->get_issuer(&xtmp, ctx, x);
+
+ if (ok < 0) return ok;
+ if (ok == 0) break;
+
+ x = xtmp;
+ if (!sk_X509_push(ctx->chain,x))
+ {
+ X509_free(xtmp);
+ OPENSSL_PUT_ERROR(X509, X509_verify_cert, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ num++;
+ }
+
+ /* we now have our chain, lets check it... */
+
+ i = check_trust(ctx);
+
+ /* If explicitly rejected error */
+ if (i == X509_TRUST_REJECTED)
+ goto end;
+ /* If not explicitly trusted then indicate error unless it's
+ * a single self signed certificate in which case we've indicated
+ * an error already and set bad_chain == 1
+ */
+ if (i != X509_TRUST_TRUSTED && !bad_chain)
+ {
+ if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
+ {
+ if (ctx->last_untrusted >= num)
+ ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
+ else
+ ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+ ctx->current_cert=x;
+ }
+ else
+ {
+
+ sk_X509_push(ctx->chain,chain_ss);
+ num++;
+ ctx->last_untrusted=num;
+ ctx->current_cert=chain_ss;
+ ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+ chain_ss=NULL;
+ }
+
+ ctx->error_depth=num-1;
+ bad_chain = 1;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+
+ /* We have the chain complete: now we need to check its purpose */
+ ok = check_chain_extensions(ctx);
+
+ if (!ok) goto end;
+
+ /* Check name constraints */
+
+ ok = check_name_constraints(ctx);
+
+ if (!ok) goto end;
+
+ ok = check_id(ctx);
+
+ if (!ok) goto end;
+
+ /* We may as well copy down any DSA parameters that are required */
+ X509_get_pubkey_parameters(NULL,ctx->chain);
+
+ /* Check revocation status: we do this after copying parameters
+ * because they may be needed for CRL signature verification.
+ */
+
+ ok = ctx->check_revocation(ctx);
+ if(!ok) goto end;
+
+ i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
+ ctx->param->flags);
+ if (i != X509_V_OK)
+ {
+ ctx->error = i;
+ ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
+ ok = cb(0, ctx);
+ if (!ok)
+ goto end;
+ }
+
+ /* At this point, we have a chain and need to verify it */
+ if (ctx->verify != NULL)
+ ok=ctx->verify(ctx);
+ else
+ ok=internal_verify(ctx);
+ if(!ok) goto end;
+
+ /* If we get this far evaluate policies */
+ if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
+ ok = ctx->check_policy(ctx);
+ if(!ok) goto end;
+ if (0)
+ {
+end:
+ X509_get_pubkey_parameters(NULL,ctx->chain);
+ }
+ if (sktmp != NULL) sk_X509_free(sktmp);
+ if (chain_ss != NULL) X509_free(chain_ss);
+ return ok;
+ }
+
+
+/* Given a STACK_OF(X509) find the issuer of cert (if any)
+ */
+
+static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
+{
+ size_t i;
+ X509 *issuer;
+ for (i = 0; i < sk_X509_num(sk); i++)
+ {
+ issuer = sk_X509_value(sk, i);
+ if (ctx->check_issued(ctx, x, issuer))
+ return issuer;
+ }
+ return NULL;
+}
+
+/* Given a possible certificate and issuer check them */
+
+static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
+{
+ int ret;
+ ret = X509_check_issued(issuer, x);
+ if (ret == X509_V_OK)
+ return 1;
+ /* If we haven't asked for issuer errors don't set ctx */
+ if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
+ return 0;
+
+ ctx->error = ret;
+ ctx->current_cert = x;
+ ctx->current_issuer = issuer;
+ return ctx->verify_cb(0, ctx);
+}
+
+/* Alternative lookup method: look from a STACK stored in other_ctx */
+
+static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
+{
+ *issuer = find_issuer(ctx, ctx->other_ctx, x);
+ if (*issuer)
+ {
+ X509_up_ref(*issuer);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
+/* Check a certificate chains extensions for consistency
+ * with the supplied purpose
+ */
+
+static int check_chain_extensions(X509_STORE_CTX *ctx)
+{
+ int i, ok=0, must_be_ca, plen = 0;
+ X509 *x;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+ int proxy_path_length = 0;
+ int purpose;
+ int allow_proxy_certs;
+ cb=ctx->verify_cb;
+
+ /* must_be_ca can have 1 of 3 values:
+ -1: we accept both CA and non-CA certificates, to allow direct
+ use of self-signed certificates (which are marked as CA).
+ 0: we only accept non-CA certificates. This is currently not
+ used, but the possibility is present for future extensions.
+ 1: we only accept CA certificates. This is currently used for
+ all certificates in the chain except the leaf certificate.
+ */
+ must_be_ca = -1;
+
+ /* CRL path validation */
+ if (ctx->parent)
+ {
+ allow_proxy_certs = 0;
+ purpose = X509_PURPOSE_CRL_SIGN;
+ }
+ else
+ {
+ allow_proxy_certs =
+ !!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
+ /* A hack to keep people who don't want to modify their
+ software happy */
+ if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
+ allow_proxy_certs = 1;
+ purpose = ctx->param->purpose;
+ }
+
+ /* Check all untrusted certificates */
+ for (i = 0; i < ctx->last_untrusted; i++)
+ {
+ int ret;
+ x = sk_X509_value(ctx->chain, i);
+ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+ && (x->ex_flags & EXFLAG_CRITICAL))
+ {
+ ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
+ {
+ ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ ret = X509_check_ca(x);
+ switch(must_be_ca)
+ {
+ case -1:
+ if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1) && (ret != 0))
+ {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_CA;
+ }
+ else
+ ret = 1;
+ break;
+ case 0:
+ if (ret != 0)
+ {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_NON_CA;
+ }
+ else
+ ret = 1;
+ break;
+ default:
+ if ((ret == 0)
+ || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1)))
+ {
+ ret = 0;
+ ctx->error = X509_V_ERR_INVALID_CA;
+ }
+ else
+ ret = 1;
+ break;
+ }
+ if (ret == 0)
+ {
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ if (ctx->param->purpose > 0)
+ {
+ ret = X509_check_purpose(x, purpose, must_be_ca > 0);
+ if ((ret == 0)
+ || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+ && (ret != 1)))
+ {
+ ctx->error = X509_V_ERR_INVALID_PURPOSE;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ }
+ /* Check pathlen if not self issued */
+ if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
+ && (x->ex_pathlen != -1)
+ && (plen > (x->ex_pathlen + proxy_path_length + 1)))
+ {
+ ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ /* Increment path length if not self issued */
+ if (!(x->ex_flags & EXFLAG_SI))
+ plen++;
+ /* If this certificate is a proxy certificate, the next
+ certificate must be another proxy certificate or a EE
+ certificate. If not, the next certificate must be a
+ CA certificate. */
+ if (x->ex_flags & EXFLAG_PROXY)
+ {
+ if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
+ {
+ ctx->error =
+ X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ok=cb(0,ctx);
+ if (!ok) goto end;
+ }
+ proxy_path_length++;
+ must_be_ca = 0;
+ }
+ else
+ must_be_ca = 1;
+ }
+ ok = 1;
+ end:
+ return ok;
+}
+
+static int check_name_constraints(X509_STORE_CTX *ctx)
+ {
+ X509 *x;
+ int i, j, rv;
+ /* Check name constraints for all certificates */
+ for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ /* Ignore self issued certs unless last in chain */
+ if (i && (x->ex_flags & EXFLAG_SI))
+ continue;
+ /* Check against constraints for all certificates higher in
+ * chain including trust anchor. Trust anchor not strictly
+ * speaking needed but if it includes constraints it is to be
+ * assumed it expects them to be obeyed.
+ */
+ for (j = sk_X509_num(ctx->chain) - 1; j > i; j--)
+ {
+ NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
+ if (nc)
+ {
+ rv = NAME_CONSTRAINTS_check(x, nc);
+ if (rv != X509_V_OK)
+ {
+ ctx->error = rv;
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ if (!ctx->verify_cb(0,ctx))
+ return 0;
+ }
+ }
+ }
+ }
+ return 1;
+ }
+
+static int check_id_error(X509_STORE_CTX *ctx, int errcode)
+ {
+ ctx->error = errcode;
+ ctx->current_cert = ctx->cert;
+ ctx->error_depth = 0;
+ return ctx->verify_cb(0, ctx);
+ }
+
+static int check_id(X509_STORE_CTX *ctx)
+ {
+ X509_VERIFY_PARAM *vpm = ctx->param;
+ X509_VERIFY_PARAM_ID *id = vpm->id;
+ X509 *x = ctx->cert;
+ if (id->host && !X509_check_host(x, id->host, id->hostlen,
+ id->hostflags))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
+ return 0;
+ }
+ if (id->email && !X509_check_email(x, id->email, id->emaillen, 0))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
+ return 0;
+ }
+ if (id->ip && !X509_check_ip(x, id->ip, id->iplen, 0))
+ {
+ if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
+ return 0;
+ }
+ return 1;
+ }
+
+static int check_trust(X509_STORE_CTX *ctx)
+{
+ size_t i;
+ int ok;
+ X509 *x = NULL;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+ cb=ctx->verify_cb;
+ /* Check all trusted certificates in chain */
+ for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ ok = X509_check_trust(x, ctx->param->trust, 0);
+ /* If explicitly trusted return trusted */
+ if (ok == X509_TRUST_TRUSTED)
+ return X509_TRUST_TRUSTED;
+ /* If explicitly rejected notify callback and reject if
+ * not overridden.
+ */
+ if (ok == X509_TRUST_REJECTED)
+ {
+ ctx->error_depth = i;
+ ctx->current_cert = x;
+ ctx->error = X509_V_ERR_CERT_REJECTED;
+ ok = cb(0, ctx);
+ if (!ok)
+ return X509_TRUST_REJECTED;
+ }
+ }
+ /* If we accept partial chains and have at least one trusted
+ * certificate return success.
+ */
+ if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
+ {
+ X509 *mx;
+ if (ctx->last_untrusted < (int) sk_X509_num(ctx->chain))
+ return X509_TRUST_TRUSTED;
+ x = sk_X509_value(ctx->chain, 0);
+ mx = lookup_cert_match(ctx, x);
+ if (mx)
+ {
+ (void)sk_X509_set(ctx->chain, 0, mx);
+ X509_free(x);
+ ctx->last_untrusted = 0;
+ return X509_TRUST_TRUSTED;
+ }
+ }
+
+ /* If no trusted certs in chain at all return untrusted and
+ * allow standard (no issuer cert) etc errors to be indicated.
+ */
+ return X509_TRUST_UNTRUSTED;
+}
+
+static int check_revocation(X509_STORE_CTX *ctx)
+ {
+ int i, last, ok;
+ if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
+ return 1;
+ if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
+ last = sk_X509_num(ctx->chain) - 1;
+ else
+ {
+ /* If checking CRL paths this isn't the EE certificate */
+ if (ctx->parent)
+ return 1;
+ last = 0;
+ }
+ for(i = 0; i <= last; i++)
+ {
+ ctx->error_depth = i;
+ ok = check_cert(ctx);
+ if (!ok) return ok;
+ }
+ return 1;
+ }
+
+static int check_cert(X509_STORE_CTX *ctx)
+ {
+ X509_CRL *crl = NULL, *dcrl = NULL;
+ X509 *x;
+ int ok, cnum;
+ unsigned int last_reasons;
+ cnum = ctx->error_depth;
+ x = sk_X509_value(ctx->chain, cnum);
+ ctx->current_cert = x;
+ ctx->current_issuer = NULL;
+ ctx->current_crl_score = 0;
+ ctx->current_reasons = 0;
+ while (ctx->current_reasons != CRLDP_ALL_REASONS)
+ {
+ last_reasons = ctx->current_reasons;
+ /* Try to retrieve relevant CRL */
+ if (ctx->get_crl)
+ ok = ctx->get_crl(ctx, &crl, x);
+ else
+ ok = get_crl_delta(ctx, &crl, &dcrl, x);
+ /* If error looking up CRL, nothing we can do except
+ * notify callback
+ */
+ if(!ok)
+ {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+ ok = ctx->verify_cb(0, ctx);
+ goto err;
+ }
+ ctx->current_crl = crl;
+ ok = ctx->check_crl(ctx, crl);
+ if (!ok)
+ goto err;
+
+ if (dcrl)
+ {
+ ok = ctx->check_crl(ctx, dcrl);
+ if (!ok)
+ goto err;
+ ok = ctx->cert_crl(ctx, dcrl, x);
+ if (!ok)
+ goto err;
+ }
+ else
+ ok = 1;
+
+ /* Don't look in full CRL if delta reason is removefromCRL */
+ if (ok != 2)
+ {
+ ok = ctx->cert_crl(ctx, crl, x);
+ if (!ok)
+ goto err;
+ }
+
+ X509_CRL_free(crl);
+ X509_CRL_free(dcrl);
+ crl = NULL;
+ dcrl = NULL;
+ /* If reasons not updated we wont get anywhere by
+ * another iteration, so exit loop.
+ */
+ if (last_reasons == ctx->current_reasons)
+ {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+ ok = ctx->verify_cb(0, ctx);
+ goto err;
+ }
+ }
+ err:
+ X509_CRL_free(crl);
+ X509_CRL_free(dcrl);
+
+ ctx->current_crl = NULL;
+ return ok;
+
+ }
+
+/* Check CRL times against values in X509_STORE_CTX */
+
+static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
+ {
+ time_t *ptime;
+ int i;
+ if (notify)
+ ctx->current_crl = crl;
+ if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ ptime = &ctx->param->check_time;
+ else
+ ptime = NULL;
+
+ i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
+ if (i == 0)
+ {
+ if (!notify)
+ return 0;
+ ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i > 0)
+ {
+ if (!notify)
+ return 0;
+ ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if(X509_CRL_get_nextUpdate(crl))
+ {
+ i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
+
+ if (i == 0)
+ {
+ if (!notify)
+ return 0;
+ ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ /* Ignore expiry of base CRL is delta is valid */
+ if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA))
+ {
+ if (!notify)
+ return 0;
+ ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ }
+
+ if (notify)
+ ctx->current_crl = NULL;
+
+ return 1;
+ }
+
+static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
+ X509 **pissuer, int *pscore, unsigned int *preasons,
+ STACK_OF(X509_CRL) *crls)
+ {
+ int crl_score, best_score = *pscore;
+ size_t i;
+ unsigned int reasons, best_reasons = 0;
+ X509 *x = ctx->current_cert;
+ X509_CRL *crl, *best_crl = NULL;
+ X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
+
+ for (i = 0; i < sk_X509_CRL_num(crls); i++)
+ {
+ crl = sk_X509_CRL_value(crls, i);
+ reasons = *preasons;
+ crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
+
+ if (crl_score > best_score)
+ {
+ best_crl = crl;
+ best_crl_issuer = crl_issuer;
+ best_score = crl_score;
+ best_reasons = reasons;
+ }
+ }
+
+ if (best_crl)
+ {
+ if (*pcrl)
+ X509_CRL_free(*pcrl);
+ *pcrl = best_crl;
+ *pissuer = best_crl_issuer;
+ *pscore = best_score;
+ *preasons = best_reasons;
+ CRYPTO_add(&best_crl->references, 1, CRYPTO_LOCK_X509_CRL);
+ if (*pdcrl)
+ {
+ X509_CRL_free(*pdcrl);
+ *pdcrl = NULL;
+ }
+ get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
+ }
+
+ if (best_score >= CRL_SCORE_VALID)
+ return 1;
+
+ return 0;
+ }
+
+/* Compare two CRL extensions for delta checking purposes. They should be
+ * both present or both absent. If both present all fields must be identical.
+ */
+
+static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
+ {
+ ASN1_OCTET_STRING *exta, *extb;
+ int i;
+ i = X509_CRL_get_ext_by_NID(a, nid, -1);
+ if (i >= 0)
+ {
+ /* Can't have multiple occurrences */
+ if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
+ return 0;
+ exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
+ }
+ else
+ exta = NULL;
+
+ i = X509_CRL_get_ext_by_NID(b, nid, -1);
+
+ if (i >= 0)
+ {
+
+ if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
+ return 0;
+ extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
+ }
+ else
+ extb = NULL;
+
+ if (!exta && !extb)
+ return 1;
+
+ if (!exta || !extb)
+ return 0;
+
+
+ if (ASN1_OCTET_STRING_cmp(exta, extb))
+ return 0;
+
+ return 1;
+ }
+
+/* See if a base and delta are compatible */
+
+static int check_delta_base(X509_CRL *delta, X509_CRL *base)
+ {
+ /* Delta CRL must be a delta */
+ if (!delta->base_crl_number)
+ return 0;
+ /* Base must have a CRL number */
+ if (!base->crl_number)
+ return 0;
+ /* Issuer names must match */
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base),
+ X509_CRL_get_issuer(delta)))
+ return 0;
+ /* AKID and IDP must match */
+ if (!crl_extension_match(delta, base, NID_authority_key_identifier))
+ return 0;
+ if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
+ return 0;
+ /* Delta CRL base number must not exceed Full CRL number. */
+ if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
+ return 0;
+ /* Delta CRL number must exceed full CRL number */
+ if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
+ return 1;
+ return 0;
+ }
+
+/* For a given base CRL find a delta... maybe extend to delta scoring
+ * or retrieve a chain of deltas...
+ */
+
+static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
+ X509_CRL *base, STACK_OF(X509_CRL) *crls)
+ {
+ X509_CRL *delta;
+ size_t i;
+ if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
+ return;
+ if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
+ return;
+ for (i = 0; i < sk_X509_CRL_num(crls); i++)
+ {
+ delta = sk_X509_CRL_value(crls, i);
+ if (check_delta_base(delta, base))
+ {
+ if (check_crl_time(ctx, delta, 0))
+ *pscore |= CRL_SCORE_TIME_DELTA;
+ CRYPTO_add(&delta->references, 1, CRYPTO_LOCK_X509_CRL);
+ *dcrl = delta;
+ return;
+ }
+ }
+ *dcrl = NULL;
+ }
+
+/* For a given CRL return how suitable it is for the supplied certificate 'x'.
+ * The return value is a mask of several criteria.
+ * If the issuer is not the certificate issuer this is returned in *pissuer.
+ * The reasons mask is also used to determine if the CRL is suitable: if
+ * no new reasons the CRL is rejected, otherwise reasons is updated.
+ */
+
+static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
+ unsigned int *preasons,
+ X509_CRL *crl, X509 *x)
+ {
+
+ int crl_score = 0;
+ unsigned int tmp_reasons = *preasons, crl_reasons;
+
+ /* First see if we can reject CRL straight away */
+
+ /* Invalid IDP cannot be processed */
+ if (crl->idp_flags & IDP_INVALID)
+ return 0;
+ /* Reason codes or indirect CRLs need extended CRL support */
+ if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
+ {
+ if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
+ return 0;
+ }
+ else if (crl->idp_flags & IDP_REASONS)
+ {
+ /* If no new reasons reject */
+ if (!(crl->idp_reasons & ~tmp_reasons))
+ return 0;
+ }
+ /* Don't process deltas at this stage */
+ else if (crl->base_crl_number)
+ return 0;
+ /* If issuer name doesn't match certificate need indirect CRL */
+ if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)))
+ {
+ if (!(crl->idp_flags & IDP_INDIRECT))
+ return 0;
+ }
+ else
+ crl_score |= CRL_SCORE_ISSUER_NAME;
+
+ if (!(crl->flags & EXFLAG_CRITICAL))
+ crl_score |= CRL_SCORE_NOCRITICAL;
+
+ /* Check expiry */
+ if (check_crl_time(ctx, crl, 0))
+ crl_score |= CRL_SCORE_TIME;
+
+ /* Check authority key ID and locate certificate issuer */
+ crl_akid_check(ctx, crl, pissuer, &crl_score);
+
+ /* If we can't locate certificate issuer at this point forget it */
+
+ if (!(crl_score & CRL_SCORE_AKID))
+ return 0;
+
+ /* Check cert for matching CRL distribution points */
+
+ if (crl_crldp_check(x, crl, crl_score, &crl_reasons))
+ {
+ /* If no new reasons reject */
+ if (!(crl_reasons & ~tmp_reasons))
+ return 0;
+ tmp_reasons |= crl_reasons;
+ crl_score |= CRL_SCORE_SCOPE;
+ }
+
+ *preasons = tmp_reasons;
+
+ return crl_score;
+
+ }
+
+static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
+ X509 **pissuer, int *pcrl_score)
+ {
+ X509 *crl_issuer = NULL;
+ X509_NAME *cnm = X509_CRL_get_issuer(crl);
+ int cidx = ctx->error_depth;
+ size_t i;
+
+ if (cidx != sk_X509_num(ctx->chain) - 1)
+ cidx++;
+
+ crl_issuer = sk_X509_value(ctx->chain, cidx);
+
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
+ {
+ if (*pcrl_score & CRL_SCORE_ISSUER_NAME)
+ {
+ *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT;
+ *pissuer = crl_issuer;
+ return;
+ }
+ }
+
+ for (cidx++; cidx < (int) sk_X509_num(ctx->chain); cidx++)
+ {
+ crl_issuer = sk_X509_value(ctx->chain, cidx);
+ if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+ continue;
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
+ {
+ *pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH;
+ *pissuer = crl_issuer;
+ return;
+ }
+ }
+
+ /* Anything else needs extended CRL support */
+
+ if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
+ return;
+
+ /* Otherwise the CRL issuer is not on the path. Look for it in the
+ * set of untrusted certificates.
+ */
+ for (i = 0; i < sk_X509_num(ctx->untrusted); i++)
+ {
+ crl_issuer = sk_X509_value(ctx->untrusted, i);
+ if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+ continue;
+ if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
+ {
+ *pissuer = crl_issuer;
+ *pcrl_score |= CRL_SCORE_AKID;
+ return;
+ }
+ }
+ }
+
+/* Check the path of a CRL issuer certificate. This creates a new
+ * X509_STORE_CTX and populates it with most of the parameters from the
+ * parent. This could be optimised somewhat since a lot of path checking
+ * will be duplicated by the parent, but this will rarely be used in
+ * practice.
+ */
+
+static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
+ {
+ X509_STORE_CTX crl_ctx;
+ int ret;
+ /* Don't allow recursive CRL path validation */
+ if (ctx->parent)
+ return 0;
+ if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
+ return -1;
+
+ crl_ctx.crls = ctx->crls;
+ /* Copy verify params across */
+ X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
+
+ crl_ctx.parent = ctx;
+ crl_ctx.verify_cb = ctx->verify_cb;
+
+ /* Verify CRL issuer */
+ ret = X509_verify_cert(&crl_ctx);
+
+ if (ret <= 0)
+ goto err;
+
+ /* Check chain is acceptable */
+
+ ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
+ err:
+ X509_STORE_CTX_cleanup(&crl_ctx);
+ return ret;
+ }
+
+/* RFC3280 says nothing about the relationship between CRL path
+ * and certificate path, which could lead to situations where a
+ * certificate could be revoked or validated by a CA not authorised
+ * to do so. RFC5280 is more strict and states that the two paths must
+ * end in the same trust anchor, though some discussions remain...
+ * until this is resolved we use the RFC5280 version
+ */
+
+static int check_crl_chain(X509_STORE_CTX *ctx,
+ STACK_OF(X509) *cert_path,
+ STACK_OF(X509) *crl_path)
+ {
+ X509 *cert_ta, *crl_ta;
+ cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
+ crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
+ if (!X509_cmp(cert_ta, crl_ta))
+ return 1;
+ return 0;
+ }
+
+/* Check for match between two dist point names: three separate cases.
+ * 1. Both are relative names and compare X509_NAME types.
+ * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
+ * 3. Both are full names and compare two GENERAL_NAMES.
+ * 4. One is NULL: automatic match.
+ */
+
+
+static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
+ {
+ X509_NAME *nm = NULL;
+ GENERAL_NAMES *gens = NULL;
+ GENERAL_NAME *gena, *genb;
+ size_t i, j;
+ if (!a || !b)
+ return 1;
+ if (a->type == 1)
+ {
+ if (!a->dpname)
+ return 0;
+ /* Case 1: two X509_NAME */
+ if (b->type == 1)
+ {
+ if (!b->dpname)
+ return 0;
+ if (!X509_NAME_cmp(a->dpname, b->dpname))
+ return 1;
+ else
+ return 0;
+ }
+ /* Case 2: set name and GENERAL_NAMES appropriately */
+ nm = a->dpname;
+ gens = b->name.fullname;
+ }
+ else if (b->type == 1)
+ {
+ if (!b->dpname)
+ return 0;
+ /* Case 2: set name and GENERAL_NAMES appropriately */
+ gens = a->name.fullname;
+ nm = b->dpname;
+ }
+
+ /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
+ if (nm)
+ {
+ for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
+ {
+ gena = sk_GENERAL_NAME_value(gens, i);
+ if (gena->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(nm, gena->d.directoryName))
+ return 1;
+ }
+ return 0;
+ }
+
+ /* Else case 3: two GENERAL_NAMES */
+
+ for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++)
+ {
+ gena = sk_GENERAL_NAME_value(a->name.fullname, i);
+ for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++)
+ {
+ genb = sk_GENERAL_NAME_value(b->name.fullname, j);
+ if (!GENERAL_NAME_cmp(gena, genb))
+ return 1;
+ }
+ }
+
+ return 0;
+
+ }
+
+static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
+ {
+ size_t i;
+ X509_NAME *nm = X509_CRL_get_issuer(crl);
+ /* If no CRLissuer return is successful iff don't need a match */
+ if (!dp->CRLissuer)
+ return !!(crl_score & CRL_SCORE_ISSUER_NAME);
+ for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
+ {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+ if (gen->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(gen->d.directoryName, nm))
+ return 1;
+ }
+ return 0;
+ }
+
+/* Check CRLDP and IDP */
+
+static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
+ unsigned int *preasons)
+ {
+ size_t i;
+ if (crl->idp_flags & IDP_ONLYATTR)
+ return 0;
+ if (x->ex_flags & EXFLAG_CA)
+ {
+ if (crl->idp_flags & IDP_ONLYUSER)
+ return 0;
+ }
+ else
+ {
+ if (crl->idp_flags & IDP_ONLYCA)
+ return 0;
+ }
+ *preasons = crl->idp_reasons;
+ for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
+ {
+ DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
+ if (crldp_check_crlissuer(dp, crl, crl_score))
+ {
+ if (!crl->idp ||
+ idp_check_dp(dp->distpoint, crl->idp->distpoint))
+ {
+ *preasons &= dp->dp_reasons;
+ return 1;
+ }
+ }
+ }
+ if ((!crl->idp || !crl->idp->distpoint) && (crl_score & CRL_SCORE_ISSUER_NAME))
+ return 1;
+ return 0;
+ }
+
+/* Retrieve CRL corresponding to current certificate.
+ * If deltas enabled try to find a delta CRL too
+ */
+
+static int get_crl_delta(X509_STORE_CTX *ctx,
+ X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
+ {
+ int ok;
+ X509 *issuer = NULL;
+ int crl_score = 0;
+ unsigned int reasons;
+ X509_CRL *crl = NULL, *dcrl = NULL;
+ STACK_OF(X509_CRL) *skcrl;
+ X509_NAME *nm = X509_get_issuer_name(x);
+ reasons = ctx->current_reasons;
+ ok = get_crl_sk(ctx, &crl, &dcrl,
+ &issuer, &crl_score, &reasons, ctx->crls);
+
+ if (ok)
+ goto done;
+
+ /* Lookup CRLs from store */
+
+ skcrl = ctx->lookup_crls(ctx, nm);
+
+ /* If no CRLs found and a near match from get_crl_sk use that */
+ if (!skcrl && crl)
+ goto done;
+
+ get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
+
+ sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
+
+ done:
+
+ /* If we got any kind of CRL use it and return success */
+ if (crl)
+ {
+ ctx->current_issuer = issuer;
+ ctx->current_crl_score = crl_score;
+ ctx->current_reasons = reasons;
+ *pcrl = crl;
+ *pdcrl = dcrl;
+ return 1;
+ }
+
+ return 0;
+ }
+
+/* Check CRL validity */
+static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
+ {
+ X509 *issuer = NULL;
+ EVP_PKEY *ikey = NULL;
+ int ok = 0, chnum, cnum;
+ cnum = ctx->error_depth;
+ chnum = sk_X509_num(ctx->chain) - 1;
+ /* if we have an alternative CRL issuer cert use that */
+ if (ctx->current_issuer)
+ issuer = ctx->current_issuer;
+
+ /* Else find CRL issuer: if not last certificate then issuer
+ * is next certificate in chain.
+ */
+ else if (cnum < chnum)
+ issuer = sk_X509_value(ctx->chain, cnum + 1);
+ else
+ {
+ issuer = sk_X509_value(ctx->chain, chnum);
+ /* If not self signed, can't check signature */
+ if(!ctx->check_issued(ctx, issuer, issuer))
+ {
+ ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok) goto err;
+ }
+ }
+
+ if(issuer)
+ {
+ /* Skip most tests for deltas because they have already
+ * been done
+ */
+ if (!crl->base_crl_number)
+ {
+ /* Check for cRLSign bit if keyUsage present */
+ if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
+ !(issuer->ex_kusage & KU_CRL_SIGN))
+ {
+ ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok) goto err;
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_SCOPE))
+ {
+ ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok) goto err;
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
+ {
+ if (check_crl_path(ctx, ctx->current_issuer) <= 0)
+ {
+ ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok) goto err;
+ }
+ }
+
+ if (crl->idp_flags & IDP_INVALID)
+ {
+ ctx->error = X509_V_ERR_INVALID_EXTENSION;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok) goto err;
+ }
+
+
+ }
+
+ if (!(ctx->current_crl_score & CRL_SCORE_TIME))
+ {
+ ok = check_crl_time(ctx, crl, 1);
+ if (!ok)
+ goto err;
+ }
+
+ /* Attempt to get issuer certificate public key */
+ ikey = X509_get_pubkey(issuer);
+
+ if(!ikey)
+ {
+ ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok) goto err;
+ }
+ else
+ {
+ int rv;
+ rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
+ if (rv != X509_V_OK)
+ {
+ ctx->error=rv;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ goto err;
+ }
+ /* Verify CRL signature */
+ if(X509_CRL_verify(crl, ikey) <= 0)
+ {
+ ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok) goto err;
+ }
+ }
+ }
+
+ ok = 1;
+
+ err:
+ EVP_PKEY_free(ikey);
+ return ok;
+ }
+
+/* Check certificate against CRL */
+static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
+ {
+ int ok;
+ X509_REVOKED *rev;
+ /* The rules changed for this... previously if a CRL contained
+ * unhandled critical extensions it could still be used to indicate
+ * a certificate was revoked. This has since been changed since
+ * critical extension can change the meaning of CRL entries.
+ */
+ if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+ && (crl->flags & EXFLAG_CRITICAL))
+ {
+ ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
+ ok = ctx->verify_cb(0, ctx);
+ if(!ok)
+ return 0;
+ }
+ /* Look for serial number of certificate in CRL
+ * If found make sure reason is not removeFromCRL.
+ */
+ if (X509_CRL_get0_by_cert(crl, &rev, x))
+ {
+ if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+ return 2;
+ ctx->error = X509_V_ERR_CERT_REVOKED;
+ ok = ctx->verify_cb(0, ctx);
+ if (!ok)
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int check_policy(X509_STORE_CTX *ctx)
+ {
+ int ret;
+ if (ctx->parent)
+ return 1;
+ ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
+ ctx->param->policies, ctx->param->flags);
+ if (ret == 0)
+ {
+ OPENSSL_PUT_ERROR(X509, check_policy, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ /* Invalid or inconsistent extensions */
+ if (ret == -1)
+ {
+ /* Locate certificates with bad extensions and notify
+ * callback.
+ */
+ X509 *x;
+ size_t i;
+ for (i = 1; i < sk_X509_num(ctx->chain); i++)
+ {
+ x = sk_X509_value(ctx->chain, i);
+ if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
+ continue;
+ ctx->current_cert = x;
+ ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
+ if(!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+ return 1;
+ }
+ if (ret == -2)
+ {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
+ return ctx->verify_cb(0, ctx);
+ }
+
+ if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
+ {
+ ctx->current_cert = NULL;
+ ctx->error = X509_V_OK;
+ if (!ctx->verify_cb(2, ctx))
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
+ {
+ time_t *ptime;
+ int i;
+
+ if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+ ptime = &ctx->param->check_time;
+ else
+ ptime = NULL;
+
+ i=X509_cmp_time(X509_get_notBefore(x), ptime);
+ if (i == 0)
+ {
+ ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i > 0)
+ {
+ ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ i=X509_cmp_time(X509_get_notAfter(x), ptime);
+ if (i == 0)
+ {
+ ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ if (i < 0)
+ {
+ ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
+ ctx->current_cert=x;
+ if (!ctx->verify_cb(0, ctx))
+ return 0;
+ }
+
+ return 1;
+ }
+
+static int internal_verify(X509_STORE_CTX *ctx)
+ {
+ int ok=0,n;
+ X509 *xs,*xi;
+ EVP_PKEY *pkey=NULL;
+ int (*cb)(int xok,X509_STORE_CTX *xctx);
+
+ cb=ctx->verify_cb;
+
+ n=sk_X509_num(ctx->chain);
+ ctx->error_depth=n-1;
+ n--;
+ xi=sk_X509_value(ctx->chain,n);
+
+ if (ctx->check_issued(ctx, xi, xi))
+ xs=xi;
+ else
+ {
+ if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
+ {
+ xs = xi;
+ goto check_cert;
+ }
+ if (n <= 0)
+ {
+ ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+ ctx->current_cert=xi;
+ ok=cb(0,ctx);
+ goto end;
+ }
+ else
+ {
+ n--;
+ ctx->error_depth=n;
+ xs=sk_X509_value(ctx->chain,n);
+ }
+ }
+
+/* ctx->error=0; not needed */
+ while (n >= 0)
+ {
+ ctx->error_depth=n;
+
+ /* Skip signature check for self signed certificates unless
+ * explicitly asked for. It doesn't add any security and
+ * just wastes time.
+ */
+ if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
+ {
+ if ((pkey=X509_get_pubkey(xi)) == NULL)
+ {
+ ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+ ctx->current_cert=xi;
+ ok=(*cb)(0,ctx);
+ if (!ok) goto end;
+ }
+ else if (X509_verify(xs,pkey) <= 0)
+ {
+ ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
+ ctx->current_cert=xs;
+ ok=(*cb)(0,ctx);
+ if (!ok)
+ {
+ EVP_PKEY_free(pkey);
+ goto end;
+ }
+ }
+ EVP_PKEY_free(pkey);
+ pkey=NULL;
+ }
+
+ xs->valid = 1;
+
+ check_cert:
+ ok = check_cert_time(ctx, xs);
+ if (!ok)
+ goto end;
+
+ /* The last error (if any) is still in the error value */
+ ctx->current_issuer=xi;
+ ctx->current_cert=xs;
+ ok=(*cb)(1,ctx);
+ if (!ok) goto end;
+
+ n--;
+ if (n >= 0)
+ {
+ xi=xs;
+ xs=sk_X509_value(ctx->chain,n);
+ }
+ }
+ ok=1;
+end:
+ return ok;
+ }
+
+int X509_cmp_current_time(const ASN1_TIME *ctm)
+{
+ return X509_cmp_time(ctm, NULL);
+}
+
+int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
+ {
+ char *str;
+ ASN1_TIME atm;
+ long offset;
+ char buff1[24],buff2[24],*p;
+ int i,j;
+
+ p=buff1;
+ i=ctm->length;
+ str=(char *)ctm->data;
+ if (ctm->type == V_ASN1_UTCTIME)
+ {
+ if ((i < 11) || (i > 17)) return 0;
+ memcpy(p,str,10);
+ p+=10;
+ str+=10;
+ }
+ else
+ {
+ if (i < 13) return 0;
+ memcpy(p,str,12);
+ p+=12;
+ str+=12;
+ }
+
+ if ((*str == 'Z') || (*str == '-') || (*str == '+'))
+ { *(p++)='0'; *(p++)='0'; }
+ else
+ {
+ *(p++)= *(str++);
+ *(p++)= *(str++);
+ /* Skip any fractional seconds... */
+ if (*str == '.')
+ {
+ str++;
+ while ((*str >= '0') && (*str <= '9')) str++;
+ }
+
+ }
+ *(p++)='Z';
+ *(p++)='\0';
+
+ if (*str == 'Z')
+ offset=0;
+ else
+ {
+ if ((*str != '+') && (*str != '-'))
+ return 0;
+ offset=((str[1]-'0')*10+(str[2]-'0'))*60;
+ offset+=(str[3]-'0')*10+(str[4]-'0');
+ if (*str == '-')
+ offset= -offset;
+ }
+ atm.type=ctm->type;
+ atm.flags = 0;
+ atm.length=sizeof(buff2);
+ atm.data=(unsigned char *)buff2;
+
+ if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
+ return 0;
+
+ if (ctm->type == V_ASN1_UTCTIME)
+ {
+ i=(buff1[0]-'0')*10+(buff1[1]-'0');
+ if (i < 50) i+=100; /* cf. RFC 2459 */
+ j=(buff2[0]-'0')*10+(buff2[1]-'0');
+ if (j < 50) j+=100;
+
+ if (i < j) return -1;
+ if (i > j) return 1;
+ }
+ i=strcmp(buff1,buff2);
+ if (i == 0) /* wait a second then return younger :-) */
+ return -1;
+ else
+ return i;
+ }
+
+ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
+{
+ return X509_time_adj(s, adj, NULL);
+}
+
+ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
+ {
+ return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+ }
+
+ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
+ int offset_day, long offset_sec, time_t *in_tm)
+ {
+ time_t t = 0;
+
+ if (in_tm) t = *in_tm;
+ else time(&t);
+
+ if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
+ {
+ if (s->type == V_ASN1_UTCTIME)
+ return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
+ if (s->type == V_ASN1_GENERALIZEDTIME)
+ return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
+ offset_sec);
+ }
+ return ASN1_TIME_adj(s, t, offset_day, offset_sec);
+ }
+
+int X509_get_pubkey_parameters(EVP_PKEY *pkey, STACK_OF(X509) *chain)
+ {
+ EVP_PKEY *ktmp=NULL,*ktmp2;
+ size_t i,j;
+
+ if ((pkey != NULL) && !EVP_PKEY_missing_parameters(pkey)) return 1;
+
+ for (i=0; i<sk_X509_num(chain); i++)
+ {
+ ktmp=X509_get_pubkey(sk_X509_value(chain,i));
+ if (ktmp == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY);
+ return 0;
+ }
+ if (!EVP_PKEY_missing_parameters(ktmp))
+ break;
+ else
+ {
+ EVP_PKEY_free(ktmp);
+ ktmp=NULL;
+ }
+ }
+ if (ktmp == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_get_pubkey_parameters, X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN);
+ return 0;
+ }
+
+ /* first, populate the other certs */
+ for (j=i-1; j < i; j--)
+ {
+ ktmp2=X509_get_pubkey(sk_X509_value(chain,j));
+ EVP_PKEY_copy_parameters(ktmp2,ktmp);
+ EVP_PKEY_free(ktmp2);
+ }
+
+ if (pkey != NULL) EVP_PKEY_copy_parameters(pkey,ktmp);
+ EVP_PKEY_free(ktmp);
+ return 1;
+ }
+
+/* Make a delta CRL as the diff between two full CRLs */
+
+X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
+ EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
+ {
+ X509_CRL *crl = NULL;
+ int i;
+ size_t j;
+ STACK_OF(X509_REVOKED) *revs = NULL;
+ /* CRLs can't be delta already */
+ if (base->base_crl_number || newer->base_crl_number)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_CRL_ALREADY_DELTA);
+ return NULL;
+ }
+ /* Base and new CRL must have a CRL number */
+ if (!base->crl_number || !newer->crl_number)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_NO_CRL_NUMBER);
+ return NULL;
+ }
+ /* Issuer names must match */
+ if (X509_NAME_cmp(X509_CRL_get_issuer(base),
+ X509_CRL_get_issuer(newer)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_ISSUER_MISMATCH);
+ return NULL;
+ }
+ /* AKID and IDP must match */
+ if (!crl_extension_match(base, newer, NID_authority_key_identifier))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_AKID_MISMATCH);
+ return NULL;
+ }
+ if (!crl_extension_match(base, newer, NID_issuing_distribution_point))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_IDP_MISMATCH);
+ return NULL;
+ }
+ /* Newer CRL number must exceed full CRL number */
+ if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_NEWER_CRL_NOT_NEWER);
+ return NULL;
+ }
+ /* CRLs must verify */
+ if (skey && (X509_CRL_verify(base, skey) <= 0 ||
+ X509_CRL_verify(newer, skey) <= 0))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, X509_R_CRL_VERIFY_FAILURE);
+ return NULL;
+ }
+ /* Create new CRL */
+ crl = X509_CRL_new();
+ if (!crl || !X509_CRL_set_version(crl, 1))
+ goto memerr;
+ /* Set issuer name */
+ if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
+ goto memerr;
+
+ if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
+ goto memerr;
+ if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
+ goto memerr;
+
+ /* Set base CRL number: must be critical */
+
+ if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
+ goto memerr;
+
+ /* Copy extensions across from newest CRL to delta: this will set
+ * CRL number to correct value too.
+ */
+
+ for (i = 0; i < X509_CRL_get_ext_count(newer); i++)
+ {
+ X509_EXTENSION *ext;
+ ext = X509_CRL_get_ext(newer, i);
+ if (!X509_CRL_add_ext(crl, ext, -1))
+ goto memerr;
+ }
+
+ /* Go through revoked entries, copying as needed */
+
+ revs = X509_CRL_get_REVOKED(newer);
+
+ for (j = 0; j < sk_X509_REVOKED_num(revs); j++)
+ {
+ X509_REVOKED *rvn, *rvtmp;
+ rvn = sk_X509_REVOKED_value(revs, j);
+ /* Add only if not also in base.
+ * TODO: need something cleverer here for some more complex
+ * CRLs covering multiple CAs.
+ */
+ if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber))
+ {
+ rvtmp = X509_REVOKED_dup(rvn);
+ if (!rvtmp)
+ goto memerr;
+ if (!X509_CRL_add0_revoked(crl, rvtmp))
+ {
+ X509_REVOKED_free(rvtmp);
+ goto memerr;
+ }
+ }
+ }
+ /* TODO: optionally prune deleted entries */
+
+ if (skey && md && !X509_CRL_sign(crl, skey, md))
+ goto memerr;
+
+ return crl;
+
+ memerr:
+ OPENSSL_PUT_ERROR(X509, X509_CRL_diff, ERR_R_MALLOC_FAILURE);
+ if (crl)
+ X509_CRL_free(crl);
+ return NULL;
+ }
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+ {
+ /* This function is (usually) called only once, by
+ * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE_CTX, argl, argp,
+ new_func, dup_func, free_func);
+ }
+
+int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
+ {
+ return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
+ }
+
+void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
+ {
+ return CRYPTO_get_ex_data(&ctx->ex_data,idx);
+ }
+
+int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
+ {
+ return ctx->error;
+ }
+
+void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
+ {
+ ctx->error=err;
+ }
+
+int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
+ {
+ return ctx->error_depth;
+ }
+
+X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_cert;
+ }
+
+STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
+ {
+ return ctx->chain;
+ }
+
+STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
+ {
+ if (!ctx->chain)
+ return NULL;
+ return X509_chain_up_ref(ctx->chain);
+ }
+
+X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_issuer;
+ }
+
+X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
+ {
+ return ctx->current_crl;
+ }
+
+X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
+ {
+ return ctx->parent;
+ }
+
+void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
+ {
+ ctx->cert=x;
+ }
+
+void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
+ {
+ ctx->untrusted=sk;
+ }
+
+void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
+ {
+ ctx->crls=sk;
+ }
+
+int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
+ {
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
+ }
+
+int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
+ {
+ return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
+ }
+
+/* This function is used to set the X509_STORE_CTX purpose and trust
+ * values. This is intended to be used when another structure has its
+ * own trust and purpose values which (if set) will be inherited by
+ * the ctx. If they aren't set then we will usually have a default
+ * purpose in mind which should then be used to set the trust value.
+ * An example of this is SSL use: an SSL structure will have its own
+ * purpose and trust settings which the application can set: if they
+ * aren't set then we use the default of SSL client/server.
+ */
+
+int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
+ int purpose, int trust)
+{
+ int idx;
+ /* If purpose not set use default */
+ if (!purpose) purpose = def_purpose;
+ /* If we have a purpose then check it is valid */
+ if (purpose)
+ {
+ X509_PURPOSE *ptmp;
+ idx = X509_PURPOSE_get_by_id(purpose);
+ if (idx == -1)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, X509_R_UNKNOWN_PURPOSE_ID);
+ return 0;
+ }
+ ptmp = X509_PURPOSE_get0(idx);
+ if (ptmp->trust == X509_TRUST_DEFAULT)
+ {
+ idx = X509_PURPOSE_get_by_id(def_purpose);
+ if (idx == -1)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, X509_R_UNKNOWN_PURPOSE_ID);
+ return 0;
+ }
+ ptmp = X509_PURPOSE_get0(idx);
+ }
+ /* If trust not set then get from purpose default */
+ if (!trust) trust = ptmp->trust;
+ }
+ if (trust)
+ {
+ idx = X509_TRUST_get_by_id(trust);
+ if (idx == -1)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_purpose_inherit, X509_R_UNKNOWN_TRUST_ID);
+ return 0;
+ }
+ }
+
+ if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
+ if (trust && !ctx->param->trust) ctx->param->trust = trust;
+ return 1;
+}
+
+X509_STORE_CTX *X509_STORE_CTX_new(void)
+{
+ X509_STORE_CTX *ctx;
+ ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
+ if (!ctx)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_new, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ return ctx;
+}
+
+void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
+{
+ X509_STORE_CTX_cleanup(ctx);
+ OPENSSL_free(ctx);
+}
+
+int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
+ STACK_OF(X509) *chain)
+ {
+ int ret = 1;
+ int ex_data_allocated = 0;
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ ctx->ctx=store;
+ ctx->cert=x509;
+ ctx->untrusted=chain;
+
+ if(!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx,
+ &ctx->ex_data))
+ {
+ goto err;
+ }
+ ex_data_allocated = 1;
+
+ ctx->param = X509_VERIFY_PARAM_new();
+ if (!ctx->param)
+ goto err;
+
+ /* Inherit callbacks and flags from X509_STORE if not set
+ * use defaults. */
+
+ if (store)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
+ else
+ ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
+
+ if (store)
+ {
+ ctx->verify_cb = store->verify_cb;
+ ctx->cleanup = store->cleanup;
+ }
+ else
+ ctx->cleanup = 0;
+
+ if (ret)
+ ret = X509_VERIFY_PARAM_inherit(ctx->param,
+ X509_VERIFY_PARAM_lookup("default"));
+
+ if (ret == 0)
+ goto err;
+
+ if (store && store->check_issued)
+ ctx->check_issued = store->check_issued;
+ else
+ ctx->check_issued = check_issued;
+
+ if (store && store->get_issuer)
+ ctx->get_issuer = store->get_issuer;
+ else
+ ctx->get_issuer = X509_STORE_CTX_get1_issuer;
+
+ if (store && store->verify_cb)
+ ctx->verify_cb = store->verify_cb;
+ else
+ ctx->verify_cb = null_callback;
+
+ if (store && store->verify)
+ ctx->verify = store->verify;
+ else
+ ctx->verify = internal_verify;
+
+ if (store && store->check_revocation)
+ ctx->check_revocation = store->check_revocation;
+ else
+ ctx->check_revocation = check_revocation;
+
+ if (store && store->get_crl)
+ ctx->get_crl = store->get_crl;
+ else
+ ctx->get_crl = NULL;
+
+ if (store && store->check_crl)
+ ctx->check_crl = store->check_crl;
+ else
+ ctx->check_crl = check_crl;
+
+ if (store && store->cert_crl)
+ ctx->cert_crl = store->cert_crl;
+ else
+ ctx->cert_crl = cert_crl;
+
+ if (store && store->lookup_certs)
+ ctx->lookup_certs = store->lookup_certs;
+ else
+ ctx->lookup_certs = X509_STORE_get1_certs;
+
+ if (store && store->lookup_crls)
+ ctx->lookup_crls = store->lookup_crls;
+ else
+ ctx->lookup_crls = X509_STORE_get1_crls;
+
+ ctx->check_policy = check_policy;
+
+ return 1;
+
+err:
+ if (ex_data_allocated)
+ {
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &ctx->ex_data);
+ }
+ if (ctx->param != NULL)
+ {
+ X509_VERIFY_PARAM_free(ctx->param);
+ }
+
+ memset(ctx, 0, sizeof(X509_STORE_CTX));
+ OPENSSL_PUT_ERROR(X509, X509_STORE_CTX_init, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+/* Set alternative lookup method: just a STACK of trusted certificates.
+ * This avoids X509_STORE nastiness where it isn't needed.
+ */
+
+void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
+{
+ ctx->other_ctx = sk;
+ ctx->get_issuer = get_issuer_sk;
+}
+
+void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
+ {
+ if (ctx->cleanup) ctx->cleanup(ctx);
+ if (ctx->param != NULL)
+ {
+ if (ctx->parent == NULL)
+ X509_VERIFY_PARAM_free(ctx->param);
+ ctx->param=NULL;
+ }
+ if (ctx->tree != NULL)
+ {
+ X509_policy_tree_free(ctx->tree);
+ ctx->tree=NULL;
+ }
+ if (ctx->chain != NULL)
+ {
+ sk_X509_pop_free(ctx->chain,X509_free);
+ ctx->chain=NULL;
+ }
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE_CTX, ctx, &(ctx->ex_data));
+ memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
+ }
+
+void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
+ {
+ X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+ }
+
+void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
+ {
+ X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+ }
+
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
+ {
+ X509_VERIFY_PARAM_set_time(ctx->param, t);
+ }
+
+void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
+ int (*verify_cb)(int, X509_STORE_CTX *))
+ {
+ ctx->verify_cb=verify_cb;
+ }
+
+X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
+ {
+ return ctx->tree;
+ }
+
+int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
+ {
+ return ctx->explicit_policy;
+ }
+
+int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
+ {
+ const X509_VERIFY_PARAM *param;
+ param = X509_VERIFY_PARAM_lookup(name);
+ if (!param)
+ return 0;
+ return X509_VERIFY_PARAM_inherit(ctx->param, param);
+ }
+
+X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
+ {
+ return ctx->param;
+ }
+
+void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
+ {
+ if (ctx->param)
+ X509_VERIFY_PARAM_free(ctx->param);
+ ctx->param = param;
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509)
+IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
new file mode 100644
index 0000000..3daaf61
--- /dev/null
+++ b/src/crypto/x509/x509_vpm.c
@@ -0,0 +1,588 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2004. */
+/* ====================================================================
+ * Copyright (c) 2004 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 <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/lhash.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include "vpm_int.h"
+
+
+/* X509_VERIFY_PARAM functions */
+
+static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
+ {
+ X509_VERIFY_PARAM_ID *paramid;
+ if (!param)
+ return;
+ param->name = NULL;
+ param->purpose = 0;
+ param->trust = 0;
+ /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
+ param->inh_flags = 0;
+ param->flags = 0;
+ param->depth = -1;
+ if (param->policies)
+ {
+ sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+ param->policies = NULL;
+ }
+ paramid = param->id;
+ if (paramid->host)
+ {
+ OPENSSL_free(paramid->host);
+ paramid->host = NULL;
+ paramid->hostlen = 0;
+ }
+ if (paramid->email)
+ {
+ OPENSSL_free(paramid->email);
+ paramid->email = NULL;
+ paramid->emaillen = 0;
+ }
+ if (paramid->ip)
+ {
+ OPENSSL_free(paramid->ip);
+ paramid->ip = NULL;
+ paramid->iplen = 0;
+ }
+
+ }
+
+X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
+ {
+ X509_VERIFY_PARAM *param;
+ X509_VERIFY_PARAM_ID *paramid;
+ param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
+ if (!param)
+ return NULL;
+ paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
+ if (!paramid)
+ {
+ OPENSSL_free(param);
+ return NULL;
+ }
+ memset(param, 0, sizeof(X509_VERIFY_PARAM));
+ memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
+ param->id = paramid;
+ x509_verify_param_zero(param);
+ return param;
+ }
+
+void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
+ {
+ x509_verify_param_zero(param);
+ OPENSSL_free(param->id);
+ OPENSSL_free(param);
+ }
+
+/* This function determines how parameters are "inherited" from one structure
+ * to another. There are several different ways this can happen.
+ *
+ * 1. If a child structure needs to have its values initialized from a parent
+ * they are simply copied across. For example SSL_CTX copied to SSL.
+ * 2. If the structure should take on values only if they are currently unset.
+ * For example the values in an SSL structure will take appropriate value
+ * for SSL servers or clients but only if the application has not set new
+ * ones.
+ *
+ * The "inh_flags" field determines how this function behaves.
+ *
+ * Normally any values which are set in the default are not copied from the
+ * destination and verify flags are ORed together.
+ *
+ * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
+ * to the destination. Effectively the values in "to" become default values
+ * which will be used only if nothing new is set in "from".
+ *
+ * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
+ * they are set or not. Flags is still Ored though.
+ *
+ * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
+ * of ORed.
+ *
+ * If X509_VP_FLAG_LOCKED is set then no values are copied.
+ *
+ * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
+ * after the next call.
+ */
+
+/* Macro to test if a field should be copied from src to dest */
+
+#define test_x509_verify_param_copy(field, def) \
+ (to_overwrite || \
+ ((src->field != def) && (to_default || (dest->field == def))))
+
+/* As above but for ID fields */
+
+#define test_x509_verify_param_copy_id(idf, def) \
+ test_x509_verify_param_copy(id->idf, def)
+
+/* Macro to test and copy a field if necessary */
+
+#define x509_verify_param_copy(field, def) \
+ if (test_x509_verify_param_copy(field, def)) \
+ dest->field = src->field
+
+
+int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
+ const X509_VERIFY_PARAM *src)
+ {
+ unsigned long inh_flags;
+ int to_default, to_overwrite;
+ X509_VERIFY_PARAM_ID *id;
+ if (!src)
+ return 1;
+ id = src->id;
+ inh_flags = dest->inh_flags | src->inh_flags;
+
+ if (inh_flags & X509_VP_FLAG_ONCE)
+ dest->inh_flags = 0;
+
+ if (inh_flags & X509_VP_FLAG_LOCKED)
+ return 1;
+
+ if (inh_flags & X509_VP_FLAG_DEFAULT)
+ to_default = 1;
+ else
+ to_default = 0;
+
+ if (inh_flags & X509_VP_FLAG_OVERWRITE)
+ to_overwrite = 1;
+ else
+ to_overwrite = 0;
+
+ x509_verify_param_copy(purpose, 0);
+ x509_verify_param_copy(trust, 0);
+ x509_verify_param_copy(depth, -1);
+
+ /* If overwrite or check time not set, copy across */
+
+ if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME))
+ {
+ dest->check_time = src->check_time;
+ dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
+ /* Don't need to copy flag: that is done below */
+ }
+
+ if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
+ dest->flags = 0;
+
+ dest->flags |= src->flags;
+
+ if (test_x509_verify_param_copy(policies, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
+ return 0;
+ }
+
+ if (test_x509_verify_param_copy_id(host, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_host(dest, id->host, id->hostlen))
+ return 0;
+ dest->id->hostflags = id->hostflags;
+ }
+
+ if (test_x509_verify_param_copy_id(email, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
+ return 0;
+ }
+
+ if (test_x509_verify_param_copy_id(ip, NULL))
+ {
+ if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
+ return 0;
+ }
+
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
+ const X509_VERIFY_PARAM *from)
+ {
+ unsigned long save_flags = to->inh_flags;
+ int ret;
+ to->inh_flags |= X509_VP_FLAG_DEFAULT;
+ ret = X509_VERIFY_PARAM_inherit(to, from);
+ to->inh_flags = save_flags;
+ return ret;
+ }
+
+static int int_x509_param_set1(unsigned char **pdest, size_t *pdestlen,
+ const unsigned char *src, size_t srclen)
+ {
+ void *tmp;
+ if (src)
+ {
+ if (srclen == 0)
+ {
+ tmp = BUF_strdup((char *)src);
+ srclen = strlen((char *)src);
+ }
+ else
+ tmp = BUF_memdup(src, srclen);
+ if (!tmp)
+ return 0;
+ }
+ else
+ {
+ tmp = NULL;
+ srclen = 0;
+ }
+ if (*pdest)
+ OPENSSL_free(*pdest);
+ *pdest = tmp;
+ if (pdestlen)
+ *pdestlen = srclen;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
+ {
+ if (param->name)
+ OPENSSL_free(param->name);
+ param->name = BUF_strdup(name);
+ if (param->name)
+ return 1;
+ return 0;
+ }
+
+int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
+ {
+ param->flags |= flags;
+ if (flags & X509_V_FLAG_POLICY_MASK)
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
+ {
+ param->flags &= ~flags;
+ return 1;
+ }
+
+unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
+ {
+ return param->flags;
+ }
+
+int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
+ {
+ return X509_PURPOSE_set(&param->purpose, purpose);
+ }
+
+int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
+ {
+ return X509_TRUST_set(&param->trust, trust);
+ }
+
+void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
+ {
+ param->depth = depth;
+ }
+
+void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
+ {
+ param->check_time = t;
+ param->flags |= X509_V_FLAG_USE_CHECK_TIME;
+ }
+
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
+ {
+ if (!param->policies)
+ {
+ param->policies = sk_ASN1_OBJECT_new_null();
+ if (!param->policies)
+ return 0;
+ }
+ if (!sk_ASN1_OBJECT_push(param->policies, policy))
+ return 0;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+ STACK_OF(ASN1_OBJECT) *policies)
+ {
+ size_t i;
+ ASN1_OBJECT *oid, *doid;
+ if (!param)
+ return 0;
+ if (param->policies)
+ sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+
+ if (!policies)
+ {
+ param->policies = NULL;
+ return 1;
+ }
+
+ param->policies = sk_ASN1_OBJECT_new_null();
+ if (!param->policies)
+ return 0;
+
+ for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++)
+ {
+ oid = sk_ASN1_OBJECT_value(policies, i);
+ doid = OBJ_dup(oid);
+ if (!doid)
+ return 0;
+ if (!sk_ASN1_OBJECT_push(param->policies, doid))
+ {
+ ASN1_OBJECT_free(doid);
+ return 0;
+ }
+ }
+ param->flags |= X509_V_FLAG_POLICY_CHECK;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
+ const unsigned char *name, size_t namelen)
+ {
+ return int_x509_param_set1(&param->id->host, &param->id->hostlen,
+ name, namelen);
+ }
+
+void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
+ unsigned int flags)
+ {
+ param->id->hostflags = flags;
+ }
+
+int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
+ const unsigned char *email, size_t emaillen)
+ {
+ return int_x509_param_set1(&param->id->email, &param->id->emaillen,
+ email, emaillen);
+ }
+
+int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
+ const unsigned char *ip, size_t iplen)
+ {
+ if (iplen != 0 && iplen != 4 && iplen != 16)
+ return 0;
+ return int_x509_param_set1(&param->id->ip, &param->id->iplen, ip, iplen);
+ }
+
+int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
+ {
+ unsigned char ipout[16];
+ int iplen;
+ iplen = a2i_ipadd(ipout, ipasc);
+ if (iplen == 0)
+ return 0;
+ return X509_VERIFY_PARAM_set1_ip(param, ipout, (size_t)iplen);
+ }
+
+int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
+ {
+ return param->depth;
+ }
+
+const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
+ {
+ return param->name;
+ }
+
+static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0, 0U, NULL, 0, NULL, 0};
+
+#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
+
+/* Default verify parameters: these are used for various
+ * applications and can be overridden by the user specified table.
+ * NB: the 'name' field *must* be in alphabetical order because it
+ * will be searched using OBJ_search.
+ */
+
+static const X509_VERIFY_PARAM default_table[] = {
+ {
+ (char *) "default", /* X509 default parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ 0, /* purpose */
+ 0, /* trust */
+ 100, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "pkcs7", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "smime_sign", /* S/MIME sign parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SMIME_SIGN, /* purpose */
+ X509_TRUST_EMAIL, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "ssl_client", /* SSL/TLS client parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_CLIENT, /* purpose */
+ X509_TRUST_SSL_CLIENT, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ },
+ {
+ (char *) "ssl_server", /* SSL/TLS server parameters */
+ 0, /* Check time */
+ 0, /* internal flags */
+ 0, /* flags */
+ X509_PURPOSE_SSL_SERVER, /* purpose */
+ X509_TRUST_SSL_SERVER, /* trust */
+ -1, /* depth */
+ NULL, /* policies */
+ vpm_empty_id
+ }};
+
+static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
+
+static int param_cmp(const X509_VERIFY_PARAM **a,
+ const X509_VERIFY_PARAM **b)
+ {
+ return strcmp((*a)->name, (*b)->name);
+ }
+
+int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
+ {
+ X509_VERIFY_PARAM *ptmp;
+ if (!param_table)
+ {
+ param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
+ if (!param_table)
+ return 0;
+ }
+ else
+ {
+ size_t idx;
+
+ if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param))
+ {
+ ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
+ X509_VERIFY_PARAM_free(ptmp);
+ (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
+ }
+ }
+ if (!sk_X509_VERIFY_PARAM_push(param_table, param))
+ return 0;
+ return 1;
+ }
+
+int X509_VERIFY_PARAM_get_count(void)
+ {
+ int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
+ if (param_table)
+ num += sk_X509_VERIFY_PARAM_num(param_table);
+ return num;
+ }
+
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
+ {
+ int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
+ if (id < num)
+ return default_table + id;
+ return sk_X509_VERIFY_PARAM_value(param_table, id - num);
+ }
+
+const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
+ {
+ X509_VERIFY_PARAM pm;
+ unsigned i, limit;
+
+ pm.name = (char *)name;
+ if (param_table)
+ {
+ size_t idx;
+ if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
+ return sk_X509_VERIFY_PARAM_value(param_table, idx);
+ }
+
+ limit = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
+ for (i = 0; i < limit; i++) {
+ if (strcmp(default_table[i].name, name) == 0) {
+ return &default_table[i];
+ }
+ }
+ return NULL;
+ }
+
+void X509_VERIFY_PARAM_table_cleanup(void)
+ {
+ if (param_table)
+ sk_X509_VERIFY_PARAM_pop_free(param_table,
+ X509_VERIFY_PARAM_free);
+ param_table = NULL;
+ }
diff --git a/src/crypto/x509/x509cset.c b/src/crypto/x509/x509cset.c
new file mode 100644
index 0000000..b526c69
--- /dev/null
+++ b/src/crypto/x509/x509cset.c
@@ -0,0 +1,165 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2001. */
+/* ====================================================================
+ * Copyright (c) 2001 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 <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_CRL_set_version(X509_CRL *x, long version)
+ {
+ if (x == NULL) return(0);
+ if (x->crl->version == NULL)
+ {
+ if ((x->crl->version=M_ASN1_INTEGER_new()) == NULL)
+ return(0);
+ }
+ return(ASN1_INTEGER_set(x->crl->version,version));
+ }
+
+int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->crl == NULL)) return(0);
+ return(X509_NAME_set(&x->crl->issuer,name));
+ }
+
+
+int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm)
+ {
+ ASN1_TIME *in;
+
+ if (x == NULL) return(0);
+ in=x->crl->lastUpdate;
+ if (in != tm)
+ {
+ in=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->crl->lastUpdate);
+ x->crl->lastUpdate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm)
+ {
+ ASN1_TIME *in;
+
+ if (x == NULL) return(0);
+ in=x->crl->nextUpdate;
+ if (in != tm)
+ {
+ in=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->crl->nextUpdate);
+ x->crl->nextUpdate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_CRL_sort(X509_CRL *c)
+ {
+ size_t i;
+ X509_REVOKED *r;
+ /* sort the data so it will be written in serial
+ * number order */
+ sk_X509_REVOKED_sort(c->crl->revoked);
+ for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++)
+ {
+ r=sk_X509_REVOKED_value(c->crl->revoked,i);
+ r->sequence=i;
+ }
+ c->crl->enc.modified = 1;
+ return 1;
+ }
+
+int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm)
+ {
+ ASN1_TIME *in;
+
+ if (x == NULL) return(0);
+ in=x->revocationDate;
+ if (in != tm)
+ {
+ in=M_ASN1_TIME_dup(tm);
+ if (in != NULL)
+ {
+ M_ASN1_TIME_free(x->revocationDate);
+ x->revocationDate=in;
+ }
+ }
+ return(in != NULL);
+ }
+
+int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial)
+ {
+ ASN1_INTEGER *in;
+
+ if (x == NULL) return(0);
+ in=x->serialNumber;
+ if (in != serial)
+ {
+ in=M_ASN1_INTEGER_dup(serial);
+ if (in != NULL)
+ {
+ M_ASN1_INTEGER_free(x->serialNumber);
+ x->serialNumber=in;
+ }
+ }
+ return(in != NULL);
+ }
diff --git a/src/crypto/x509/x509name.c b/src/crypto/x509/x509name.c
new file mode 100644
index 0000000..042d18b
--- /dev/null
+++ b/src/crypto/x509/x509name.c
@@ -0,0 +1,381 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-1);
+ return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
+ }
+
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf,
+ int len)
+ {
+ int i;
+ ASN1_STRING *data;
+
+ i=X509_NAME_get_index_by_OBJ(name,obj,-1);
+ if (i < 0) return(-1);
+ data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
+ i=(data->length > (len-1))?(len-1):data->length;
+ if (buf == NULL) return(data->length);
+ memcpy(buf,data->data,i);
+ buf[i]='\0';
+ return(i);
+ }
+
+int X509_NAME_entry_count(X509_NAME *name)
+ {
+ if (name == NULL) return(0);
+ return(sk_X509_NAME_ENTRY_num(name->entries));
+ }
+
+int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
+ {
+ const ASN1_OBJECT *obj;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL) return(-2);
+ return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
+ }
+
+/* NOTE: you should be passsing -1, not 0 as lastpos */
+int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+ int lastpos)
+ {
+ int n;
+ X509_NAME_ENTRY *ne;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL) return(-1);
+ if (lastpos < 0)
+ lastpos= -1;
+ sk=name->entries;
+ n=sk_X509_NAME_ENTRY_num(sk);
+ for (lastpos++; lastpos < n; lastpos++)
+ {
+ ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
+ if (OBJ_cmp(ne->object,obj) == 0)
+ return(lastpos);
+ }
+ return(-1);
+ }
+
+X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
+ {
+ if(name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
+ return(NULL);
+ else
+ return(sk_X509_NAME_ENTRY_value(name->entries,loc));
+ }
+
+X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
+ {
+ X509_NAME_ENTRY *ret;
+ int i,n,set_prev,set_next;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
+ return(NULL);
+ sk=name->entries;
+ ret=sk_X509_NAME_ENTRY_delete(sk,loc);
+ n=sk_X509_NAME_ENTRY_num(sk);
+ name->modified=1;
+ if (loc == n) return(ret);
+
+ /* else we need to fixup the set field */
+ if (loc != 0)
+ set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
+ else
+ set_prev=ret->set-1;
+ set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
+
+ /* set_prev is the previous set
+ * set is the current set
+ * set_next is the following
+ * prev 1 1 1 1 1 1 1 1
+ * set 1 1 2 2
+ * next 1 1 2 2 2 2 3 2
+ * so basically only if prev and next differ by 2, then
+ * re-number down by 1 */
+ if (set_prev+1 < set_next)
+ for (i=loc; i<n; i++)
+ sk_X509_NAME_ENTRY_value(sk,i)->set--;
+ return(ret);
+ }
+
+int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
+ unsigned char *bytes, int len, int loc, int set)
+{
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
+ if(!ne) return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
+}
+
+int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
+ unsigned char *bytes, int len, int loc, int set)
+{
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+ if(!ne) return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
+}
+
+int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
+ const unsigned char *bytes, int len, int loc, int set)
+{
+ X509_NAME_ENTRY *ne;
+ int ret;
+ ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
+ if(!ne) return 0;
+ ret = X509_NAME_add_entry(name, ne, loc, set);
+ X509_NAME_ENTRY_free(ne);
+ return ret;
+}
+
+/* if set is -1, append to previous set, 0 'a new one', and 1,
+ * prepend to the guy we are about to stomp on. */
+int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
+ int set)
+ {
+ X509_NAME_ENTRY *new_name=NULL;
+ int n,i,inc;
+ STACK_OF(X509_NAME_ENTRY) *sk;
+
+ if (name == NULL) return(0);
+ sk=name->entries;
+ n=sk_X509_NAME_ENTRY_num(sk);
+ if (loc > n) loc=n;
+ else if (loc < 0) loc=n;
+
+ name->modified=1;
+
+ if (set == -1)
+ {
+ if (loc == 0)
+ {
+ set=0;
+ inc=1;
+ }
+ else
+ {
+ set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
+ inc=0;
+ }
+ }
+ else /* if (set >= 0) */
+ {
+ if (loc >= n)
+ {
+ if (loc != 0)
+ set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
+ else
+ set=0;
+ }
+ else
+ set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
+ inc=(set == 0)?1:0;
+ }
+
+ if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
+ goto err;
+ new_name->set=set;
+ if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_add_entry, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (inc)
+ {
+ n=sk_X509_NAME_ENTRY_num(sk);
+ for (i=loc+1; i<n; i++)
+ sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
+ }
+ return(1);
+err:
+ if (new_name != NULL)
+ X509_NAME_ENTRY_free(new_name);
+ return(0);
+ }
+
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
+ const char *field, int type, const unsigned char *bytes, int len)
+ {
+ ASN1_OBJECT *obj;
+ X509_NAME_ENTRY *nentry;
+
+ obj=OBJ_txt2obj(field, 0);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_create_by_txt, X509_R_INVALID_FIELD_NAME);
+ ERR_add_error_data(2, "name=", field);
+ return(NULL);
+ }
+ nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
+ ASN1_OBJECT_free(obj);
+ return nentry;
+ }
+
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
+ int type, unsigned char *bytes, int len)
+ {
+ const ASN1_OBJECT *obj;
+ X509_NAME_ENTRY *nentry;
+
+ obj=OBJ_nid2obj(nid);
+ if (obj == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_create_by_NID, X509_R_UNKNOWN_NID);
+ return(NULL);
+ }
+ nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
+ /* TODO(fork): remove this? */
+ /* ASN1_OBJECT_free(obj); */
+ return nentry;
+ }
+
+X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
+ const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
+ {
+ X509_NAME_ENTRY *ret;
+
+ if ((ne == NULL) || (*ne == NULL))
+ {
+ if ((ret=X509_NAME_ENTRY_new()) == NULL)
+ return(NULL);
+ }
+ else
+ ret= *ne;
+
+ if (!X509_NAME_ENTRY_set_object(ret,obj))
+ goto err;
+ if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
+ goto err;
+
+ if ((ne != NULL) && (*ne == NULL)) *ne=ret;
+ return(ret);
+err:
+ if ((ne == NULL) || (ret != *ne))
+ X509_NAME_ENTRY_free(ret);
+ return(NULL);
+ }
+
+int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
+ {
+ if ((ne == NULL) || (obj == NULL))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_NAME_ENTRY_set_object, ERR_R_PASSED_NULL_PARAMETER);
+ return(0);
+ }
+ ASN1_OBJECT_free(ne->object);
+ ne->object=OBJ_dup(obj);
+ return((ne->object == NULL)?0:1);
+ }
+
+int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
+ const unsigned char *bytes, int len)
+ {
+ int i;
+
+ if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
+ if((type > 0) && (type & MBSTRING_FLAG))
+ return ASN1_STRING_set_by_NID(&ne->value, bytes,
+ len, type,
+ OBJ_obj2nid(ne->object)) ? 1 : 0;
+ if (len < 0) len=strlen((const char *)bytes);
+ i=ASN1_STRING_set(ne->value,bytes,len);
+ if (!i) return(0);
+ if (type != V_ASN1_UNDEF)
+ {
+ if (type == V_ASN1_APP_CHOOSE)
+ ne->value->type=ASN1_PRINTABLE_type(bytes,len);
+ else
+ ne->value->type=type;
+ }
+ return(1);
+ }
+
+ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
+ {
+ if (ne == NULL) return(NULL);
+ return(ne->object);
+ }
+
+ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
+ {
+ if (ne == NULL) return(NULL);
+ return(ne->value);
+ }
+
diff --git a/src/crypto/x509/x509rset.c b/src/crypto/x509/x509rset.c
new file mode 100644
index 0000000..dbab555
--- /dev/null
+++ b/src/crypto/x509/x509rset.c
@@ -0,0 +1,80 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_REQ_set_version(X509_REQ *x, long version)
+ {
+ if (x == NULL) return(0);
+ return(ASN1_INTEGER_set(x->req_info->version,version));
+ }
+
+int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
+ {
+ if ((x == NULL) || (x->req_info == NULL)) return(0);
+ return(X509_NAME_set(&x->req_info->subject,name));
+ }
+
+int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
+ {
+ if ((x == NULL) || (x->req_info == NULL)) return(0);
+ return(X509_PUBKEY_set(&x->req_info->pubkey,pkey));
+ }
+
diff --git a/src/crypto/x509/x509spki.c b/src/crypto/x509/x509spki.c
new file mode 100644
index 0000000..9bab957
--- /dev/null
+++ b/src/crypto/x509/x509spki.c
@@ -0,0 +1,135 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999. */
+/* ====================================================================
+ * Copyright (c) 1999 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 <string.h>
+
+#include <openssl/base64.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+
+int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
+{
+ if ((x == NULL) || (x->spkac == NULL)) return(0);
+ return(X509_PUBKEY_set(&(x->spkac->pubkey),pkey));
+}
+
+EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x)
+{
+ if ((x == NULL) || (x->spkac == NULL))
+ return(NULL);
+ return(X509_PUBKEY_get(x->spkac->pubkey));
+}
+
+/* Load a Netscape SPKI from a base64 encoded string */
+
+NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len)
+{
+ unsigned char *spki_der;
+ const unsigned char *p;
+ size_t spki_len;
+ NETSCAPE_SPKI *spki;
+ if (len <= 0)
+ len = strlen(str);
+ if (!EVP_DecodedLength(&spki_len, len)) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
+ return NULL;
+ }
+ if (!(spki_der = OPENSSL_malloc(spki_len))) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_decode, X509_R_BASE64_DECODE_ERROR);
+ OPENSSL_free(spki_der);
+ return NULL;
+ }
+ p = spki_der;
+ spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
+ OPENSSL_free(spki_der);
+ return spki;
+}
+
+/* Generate a base64 encoded string from an SPKI */
+
+char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
+{
+ unsigned char *der_spki, *p;
+ char *b64_str;
+ size_t b64_len;
+ int der_len;
+ der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+ if (!EVP_EncodedLength(&b64_len, der_len))
+ {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_OVERFLOW);
+ return NULL;
+ }
+ der_spki = OPENSSL_malloc(der_len);
+ if (der_spki == NULL) {
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ b64_str = OPENSSL_malloc(b64_len);
+ if (b64_str == NULL) {
+ OPENSSL_free(der_spki);
+ OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ p = der_spki;
+ i2d_NETSCAPE_SPKI(spki, &p);
+ EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
+ OPENSSL_free(der_spki);
+ return b64_str;
+}
diff --git a/src/crypto/x509/x509type.c b/src/crypto/x509/x509type.c
new file mode 100644
index 0000000..e7c7935
--- /dev/null
+++ b/src/crypto/x509/x509type.c
@@ -0,0 +1,128 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
+ {
+ EVP_PKEY *pk;
+ int ret=0,i;
+
+ if (x == NULL) return(0);
+
+ if (pkey == NULL)
+ pk=X509_get_pubkey(x);
+ else
+ pk=pkey;
+
+ if (pk == NULL) return(0);
+
+ switch (pk->type)
+ {
+ case EVP_PKEY_RSA:
+ ret=EVP_PK_RSA|EVP_PKT_SIGN;
+/* if (!sign only extension) */
+ ret|=EVP_PKT_ENC;
+ break;
+ case EVP_PKEY_DSA:
+ ret=EVP_PK_DSA|EVP_PKT_SIGN;
+ break;
+ case EVP_PKEY_EC:
+ ret=EVP_PK_EC|EVP_PKT_SIGN|EVP_PKT_EXCH;
+ break;
+ case EVP_PKEY_DH:
+ ret=EVP_PK_DH|EVP_PKT_EXCH;
+ break;
+ case NID_id_GostR3410_94:
+ case NID_id_GostR3410_2001:
+ ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
+ break;
+ default:
+ break;
+ }
+
+ i=OBJ_obj2nid(x->sig_alg->algorithm);
+ if (i && OBJ_find_sigid_algs(i, NULL, &i))
+ {
+
+ switch (i)
+ {
+ case NID_rsaEncryption:
+ case NID_rsa:
+ ret|=EVP_PKS_RSA;
+ break;
+ case NID_dsa:
+ case NID_dsa_2:
+ ret|=EVP_PKS_DSA;
+ break;
+ case NID_X9_62_id_ecPublicKey:
+ ret|=EVP_PKS_EC;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look
+ for, not bytes */
+ ret|=EVP_PKT_EXP;
+ if(pkey==NULL) EVP_PKEY_free(pk);
+ return(ret);
+ }
+
diff --git a/src/crypto/x509/x_algor.c b/src/crypto/x509/x_algor.c
new file mode 100644
index 0000000..ae694e3
--- /dev/null
+++ b/src/crypto/x509/x_algor.c
@@ -0,0 +1,154 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2000. */
+/* ====================================================================
+ * Copyright (c) 2000 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 <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/obj.h>
+
+
+ASN1_SEQUENCE(X509_ALGOR) = {
+ ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
+ ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
+} ASN1_SEQUENCE_END(X509_ALGOR)
+
+ASN1_ITEM_TEMPLATE(X509_ALGORS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_ALGORS, X509_ALGORS, X509_ALGORS)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_ALGOR)
+
+IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
+
+int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, void *pval)
+ {
+ if (!alg)
+ return 0;
+ if (ptype != V_ASN1_UNDEF)
+ {
+ if (alg->parameter == NULL)
+ alg->parameter = ASN1_TYPE_new();
+ if (alg->parameter == NULL)
+ return 0;
+ }
+ if (alg)
+ {
+ if (alg->algorithm)
+ ASN1_OBJECT_free(alg->algorithm);
+ alg->algorithm = (ASN1_OBJECT*) aobj;
+ }
+ if (ptype == 0)
+ return 1;
+ if (ptype == V_ASN1_UNDEF)
+ {
+ if (alg->parameter)
+ {
+ ASN1_TYPE_free(alg->parameter);
+ alg->parameter = NULL;
+ }
+ }
+ else
+ ASN1_TYPE_set(alg->parameter, ptype, pval);
+ return 1;
+ }
+
+void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
+ X509_ALGOR *algor)
+ {
+ if (paobj)
+ *paobj = algor->algorithm;
+ if (pptype)
+ {
+ if (algor->parameter == NULL)
+ {
+ *pptype = V_ASN1_UNDEF;
+ return;
+ }
+ else
+ *pptype = algor->parameter->type;
+ if (ppval)
+ *ppval = algor->parameter->value.ptr;
+ }
+ }
+
+/* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
+
+void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
+ {
+ int param_type;
+
+ if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
+ param_type = V_ASN1_UNDEF;
+ else
+ param_type = V_ASN1_NULL;
+
+ X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+
+ }
+
+/* X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */
+int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
+ {
+ int rv;
+ rv = OBJ_cmp(a->algorithm, b->algorithm);
+ if (rv)
+ return rv;
+ if (!a->parameter && !b->parameter)
+ return 0;
+ return ASN1_TYPE_cmp(a->parameter, b->parameter);
+ }
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
new file mode 100644
index 0000000..785fd1e
--- /dev/null
+++ b/src/crypto/x509/x_all.c
@@ -0,0 +1,544 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/dsa.h>
+#include <openssl/evp.h>
+#include <openssl/rsa.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+
+extern const ASN1_ITEM RSAPrivateKey_it;
+extern const ASN1_ITEM RSAPublicKey_it;
+
+int X509_verify(X509 *a, EVP_PKEY *r)
+ {
+ if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
+ return 0;
+ return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
+ a->signature,a->cert_info,r));
+ }
+
+int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
+ {
+ return( ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
+ a->sig_alg,a->signature,a->req_info,r));
+ }
+
+int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ x->cert_info->enc.modified = 1;
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info,pkey,md));
+ }
+
+int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
+ {
+ x->cert_info->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
+ x->cert_info->signature,
+ x->sig_alg, x->signature, x->cert_info, ctx);
+ }
+
+/* TODO(fork)
+int X509_http_nbio(OCSP_REQ_CTX *rctx, X509 **pcert)
+ {
+ return OCSP_REQ_CTX_nbio_d2i(rctx,
+ (ASN1_VALUE **)pcert, ASN1_ITEM_rptr(X509));
+ }
+*/
+
+int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL,
+ x->signature, x->req_info,pkey,md));
+ }
+
+int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
+ {
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
+ x->sig_alg, NULL, x->signature, x->req_info, ctx);
+ }
+
+int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ x->crl->enc.modified = 1;
+ return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO),x->crl->sig_alg,
+ x->sig_alg, x->signature, x->crl,pkey,md));
+ }
+
+int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
+ {
+ x->crl->enc.modified = 1;
+ return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
+ x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx);
+ }
+
+/* TODO(fork)
+int X509_CRL_http_nbio(OCSP_REQ_CTX *rctx, X509_CRL **pcrl)
+ {
+ return OCSP_REQ_CTX_nbio_d2i(rctx,
+ (ASN1_VALUE **)pcrl, ASN1_ITEM_rptr(X509_CRL));
+ }
+*/
+
+int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
+ {
+ return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL,
+ x->signature, x->spkac,pkey,md));
+ }
+
+#ifndef OPENSSL_NO_FP_API
+X509 *d2i_X509_fp(FILE *fp, X509 **x509)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
+ }
+
+int i2d_X509_fp(FILE *fp, X509 *x509)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
+ }
+#endif
+
+X509 *d2i_X509_bio(BIO *bp, X509 **x509)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
+ }
+
+int i2d_X509_bio(BIO *bp, X509 *x509)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+ }
+
+int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+ }
+#endif
+
+X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+ }
+
+int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+ }
+
+/* TODO(fork) */
+#if 0
+#ifndef OPENSSL_NO_FP_API
+PKCS7 *d2i_PKCS7_fp(FILE *fp, PKCS7 **p7)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+ }
+
+int i2d_PKCS7_fp(FILE *fp, PKCS7 *p7)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(PKCS7), fp, p7);
+ }
+#endif
+
+PKCS7 *d2i_PKCS7_bio(BIO *bp, PKCS7 **p7)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+ }
+
+int i2d_PKCS7_bio(BIO *bp, PKCS7 *p7)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(PKCS7), bp, p7);
+ }
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+ }
+
+int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+ }
+#endif
+
+X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+ }
+
+int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+ }
+
+
+#ifndef OPENSSL_NO_FP_API
+RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+ }
+
+int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPrivateKey), fp, rsa);
+ }
+
+RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_item_d2i_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
+ }
+
+RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
+ {
+ return ASN1_d2i_fp((void *(*)(void))
+ RSA_new,(D2I_OF(void))d2i_RSA_PUBKEY, fp,
+ (void **)rsa);
+ }
+
+int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_item_i2d_fp(ASN1_ITEM_rptr(RSAPublicKey), fp, rsa);
+ }
+
+int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
+ {
+ return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY,fp,rsa);
+ }
+#endif
+
+RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+ }
+
+int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPrivateKey), bp, rsa);
+ }
+
+RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_item_d2i_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
+ }
+
+
+RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
+ {
+ return ASN1_d2i_bio_of(RSA,RSA_new,d2i_RSA_PUBKEY,bp,rsa);
+ }
+
+int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_item_i2d_bio(ASN1_ITEM_rptr(RSAPublicKey), bp, rsa);
+ }
+
+int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
+ {
+ return ASN1_i2d_bio_of_const(RSA,i2d_RSA_PUBKEY,bp,rsa);
+ }
+
+#ifndef OPENSSL_NO_DSA
+#ifndef OPENSSL_NO_FP_API
+DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
+ {
+ return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSAPrivateKey,fp,dsa);
+ }
+
+int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
+ {
+ return ASN1_i2d_fp_of_const(DSA,i2d_DSAPrivateKey,fp,dsa);
+ }
+
+DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
+ {
+ return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSA_PUBKEY,fp,dsa);
+ }
+
+int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
+ {
+ return ASN1_i2d_fp_of_const(DSA,i2d_DSA_PUBKEY,fp,dsa);
+ }
+#endif
+
+DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
+ {
+ return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAPrivateKey,bp,dsa
+);
+ }
+
+int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
+ {
+ return ASN1_i2d_bio_of_const(DSA,i2d_DSAPrivateKey,bp,dsa);
+ }
+
+DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
+ {
+ return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSA_PUBKEY,bp,dsa);
+ }
+
+int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
+ {
+ return ASN1_i2d_bio_of_const(DSA,i2d_DSA_PUBKEY,bp,dsa);
+ }
+
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,fp,eckey);
+ }
+
+int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_fp_of_const(EC_KEY,i2d_EC_PUBKEY,fp,eckey);
+ }
+
+EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,fp,eckey);
+ }
+
+int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_fp_of_const(EC_KEY,i2d_ECPrivateKey,fp,eckey);
+ }
+#endif
+EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,bp,eckey);
+ }
+
+int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
+ {
+ return ASN1_i2d_bio_of_const(EC_KEY,i2d_EC_PUBKEY,bp,ecdsa);
+ }
+
+EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
+ {
+ return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,bp,eckey);
+ }
+
+int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
+ {
+ return ASN1_i2d_bio_of_const(EC_KEY,i2d_ECPrivateKey,bp,eckey);
+ }
+
+
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ ASN1_BIT_STRING *key;
+ key = X509_get0_pubkey_bitstr(data);
+ if(!key) return 0;
+ return EVP_Digest(key->data, key->length, md, len, type, NULL);
+ }
+
+int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len));
+ }
+
+int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL),type,(char *)data,md,len));
+ }
+
+int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ),type,(char *)data,md,len));
+ }
+
+int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md,
+ unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME),type,(char *)data,md,len));
+ }
+
+#if 0 /* TODO(fork): remove */
+int PKCS7_ISSUER_AND_SERIAL_digest(PKCS7_ISSUER_AND_SERIAL *data, const EVP_MD *type,
+ unsigned char *md, unsigned int *len)
+ {
+ return(ASN1_item_digest(ASN1_ITEM_rptr(PKCS7_ISSUER_AND_SERIAL),type,
+ (char *)data,md,len));
+ }
+#endif
+
+#ifndef OPENSSL_NO_FP_API
+X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
+ {
+ return ASN1_d2i_fp_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,fp,p8);
+ }
+
+int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
+ {
+ return ASN1_i2d_fp_of(X509_SIG,i2d_X509_SIG,fp,p8);
+ }
+#endif
+
+X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
+ {
+ return ASN1_d2i_bio_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,bp,p8);
+ }
+
+int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
+ {
+ return ASN1_i2d_bio_of(X509_SIG,i2d_X509_SIG,bp,p8);
+ }
+
+#ifndef OPENSSL_NO_FP_API
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
+ PKCS8_PRIV_KEY_INFO **p8inf)
+ {
+ return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO,fp,p8inf);
+ }
+
+int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
+ {
+ return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,fp,
+ p8inf);
+ }
+
+int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
+ {
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ int ret;
+ p8inf = EVP_PKEY2PKCS8(key);
+ if(!p8inf) return 0;
+ ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+ }
+
+int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PrivateKey,fp,pkey);
+ }
+
+EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
+{
+ return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,fp,a);
+}
+
+int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PUBKEY,fp,pkey);
+ }
+
+EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
+{
+ return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,fp,a);
+}
+
+PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
+ PKCS8_PRIV_KEY_INFO **p8inf)
+ {
+ return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
+ d2i_PKCS8_PRIV_KEY_INFO,bp,p8inf);
+ }
+
+int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
+ {
+ return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,bp,
+ p8inf);
+ }
+
+int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
+ {
+ PKCS8_PRIV_KEY_INFO *p8inf;
+ int ret;
+ p8inf = EVP_PKEY2PKCS8(key);
+ if(!p8inf) return 0;
+ ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+ PKCS8_PRIV_KEY_INFO_free(p8inf);
+ return ret;
+ }
+#endif
+
+int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PrivateKey,bp,pkey);
+ }
+
+EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
+ {
+ return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,bp,a);
+ }
+
+int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
+ {
+ return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PUBKEY,bp,pkey);
+ }
+
+EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
+ {
+ return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,bp,a);
+ }
diff --git a/src/crypto/x509/x_attrib.c b/src/crypto/x509/x_attrib.c
new file mode 100644
index 0000000..c460a70
--- /dev/null
+++ b/src/crypto/x509/x_attrib.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+#include <openssl/obj.h>
+
+
+/* X509_ATTRIBUTE: this has the following form:
+ *
+ * typedef struct x509_attributes_st
+ * {
+ * ASN1_OBJECT *object;
+ * int single;
+ * union {
+ * char *ptr;
+ * STACK_OF(ASN1_TYPE) *set;
+ * ASN1_TYPE *single;
+ * } value;
+ * } X509_ATTRIBUTE;
+ *
+ * this needs some extra thought because the CHOICE type is
+ * merged with the main structure and because the value can
+ * be anything at all we *must* try the SET OF first because
+ * the ASN1_ANY type will swallow anything including the whole
+ * SET OF structure.
+ */
+
+ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
+ ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
+ ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
+} ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
+
+ASN1_SEQUENCE(X509_ATTRIBUTE) = {
+ ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
+ /* CHOICE type merged with parent */
+ ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
+} ASN1_SEQUENCE_END(X509_ATTRIBUTE)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
+
+X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
+ {
+ X509_ATTRIBUTE *ret=NULL;
+ ASN1_TYPE *val=NULL;
+
+ if ((ret=X509_ATTRIBUTE_new()) == NULL)
+ return(NULL);
+ /* TODO(fork): const correctness. */
+ ret->object=(ASN1_OBJECT*) OBJ_nid2obj(nid);
+ ret->single=0;
+ if ((ret->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err;
+ if ((val=ASN1_TYPE_new()) == NULL) goto err;
+ if (!sk_ASN1_TYPE_push(ret->value.set,val)) goto err;
+
+ ASN1_TYPE_set(val,atrtype,value);
+ return(ret);
+err:
+ if (ret != NULL) X509_ATTRIBUTE_free(ret);
+ if (val != NULL) ASN1_TYPE_free(val);
+ return(NULL);
+ }
diff --git a/src/crypto/x509/x_crl.c b/src/crypto/x509/x_crl.c
new file mode 100644
index 0000000..bb23b57
--- /dev/null
+++ b/src/crypto/x509/x_crl.c
@@ -0,0 +1,545 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+/* Method to handle CRL access.
+ * In general a CRL could be very large (several Mb) and can consume large
+ * amounts of resources if stored in memory by multiple processes.
+ * This method allows general CRL operations to be redirected to more
+ * efficient callbacks: for example a CRL entry database.
+ */
+
+#define X509_CRL_METHOD_DYNAMIC 1
+
+struct x509_crl_method_st
+ {
+ int flags;
+ int (*crl_init)(X509_CRL *crl);
+ int (*crl_free)(X509_CRL *crl);
+ int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
+ ASN1_INTEGER *ser, X509_NAME *issuer);
+ int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
+ };
+
+static int X509_REVOKED_cmp(const X509_REVOKED **a,
+ const X509_REVOKED **b);
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
+
+ASN1_SEQUENCE(X509_REVOKED) = {
+ ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
+} ASN1_SEQUENCE_END(X509_REVOKED)
+
+static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
+static int def_crl_lookup(X509_CRL *crl,
+ X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer);
+
+static const X509_CRL_METHOD int_crl_meth =
+ {
+ 0,
+ 0,0,
+ def_crl_lookup,
+ def_crl_verify
+ };
+
+static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
+
+/* The X509_CRL_INFO structure needs a bit of customisation.
+ * Since we cache the original encoding the signature wont be affected by
+ * reordering of the revoked field.
+ */
+static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
+
+ if(!a || !a->revoked) return 1;
+ switch(operation) {
+ /* Just set cmp function here. We don't sort because that
+ * would affect the output of X509_CRL_print().
+ */
+ case ASN1_OP_D2I_POST:
+ (void)sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
+ break;
+ }
+ return 1;
+}
+
+
+ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
+ ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
+ ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
+ ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
+} ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
+
+/* Set CRL entry issuer according to CRL certificate issuer extension.
+ * Check for unhandled critical CRL entry extensions.
+ */
+
+static int crl_set_issuers(X509_CRL *crl)
+ {
+
+ size_t i, k;
+ int j;
+ GENERAL_NAMES *gens, *gtmp;
+ STACK_OF(X509_REVOKED) *revoked;
+
+ revoked = X509_CRL_get_REVOKED(crl);
+
+ gens = NULL;
+ for (i = 0; i < sk_X509_REVOKED_num(revoked); i++)
+ {
+ X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
+ STACK_OF(X509_EXTENSION) *exts;
+ ASN1_ENUMERATED *reason;
+ X509_EXTENSION *ext;
+ gtmp = X509_REVOKED_get_ext_d2i(rev,
+ NID_certificate_issuer,
+ &j, NULL);
+ if (!gtmp && (j != -1))
+ {
+ crl->flags |= EXFLAG_INVALID;
+ return 1;
+ }
+
+ if (gtmp)
+ {
+ gens = gtmp;
+ if (!crl->issuers)
+ {
+ crl->issuers = sk_GENERAL_NAMES_new_null();
+ if (!crl->issuers)
+ return 0;
+ }
+ if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
+ return 0;
+ }
+ rev->issuer = gens;
+
+ reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
+ &j, NULL);
+ if (!reason && (j != -1))
+ {
+ crl->flags |= EXFLAG_INVALID;
+ return 1;
+ }
+
+ if (reason)
+ {
+ rev->reason = ASN1_ENUMERATED_get(reason);
+ ASN1_ENUMERATED_free(reason);
+ }
+ else
+ rev->reason = CRL_REASON_NONE;
+
+ /* Check for critical CRL entry extensions */
+
+ exts = rev->extensions;
+
+ for (k = 0; k < sk_X509_EXTENSION_num(exts); k++)
+ {
+ ext = sk_X509_EXTENSION_value(exts, k);
+ if (ext->critical > 0)
+ {
+ if (OBJ_obj2nid(ext->object) ==
+ NID_certificate_issuer)
+ continue;
+ crl->flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
+
+
+ }
+
+ return 1;
+
+ }
+
+/* The X509_CRL structure needs a bit of customisation. Cache some extensions
+ * and hash of the whole CRL.
+ */
+static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+ {
+ X509_CRL *crl = (X509_CRL *)*pval;
+ STACK_OF(X509_EXTENSION) *exts;
+ X509_EXTENSION *ext;
+ size_t idx;
+
+ switch(operation)
+ {
+ case ASN1_OP_NEW_POST:
+ crl->idp = NULL;
+ crl->akid = NULL;
+ crl->flags = 0;
+ crl->idp_flags = 0;
+ crl->idp_reasons = CRLDP_ALL_REASONS;
+ crl->meth = default_crl_method;
+ crl->meth_data = NULL;
+ crl->issuers = NULL;
+ crl->crl_number = NULL;
+ crl->base_crl_number = NULL;
+ break;
+
+ case ASN1_OP_D2I_POST:
+ X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
+ crl->idp = X509_CRL_get_ext_d2i(crl,
+ NID_issuing_distribution_point, NULL, NULL);
+ if (crl->idp)
+ setup_idp(crl, crl->idp);
+
+ crl->akid = X509_CRL_get_ext_d2i(crl,
+ NID_authority_key_identifier, NULL, NULL);
+
+ crl->crl_number = X509_CRL_get_ext_d2i(crl,
+ NID_crl_number, NULL, NULL);
+
+ crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
+ NID_delta_crl, NULL, NULL);
+ /* Delta CRLs must have CRL number */
+ if (crl->base_crl_number && !crl->crl_number)
+ crl->flags |= EXFLAG_INVALID;
+
+ /* See if we have any unhandled critical CRL extensions and
+ * indicate this in a flag. We only currently handle IDP so
+ * anything else critical sets the flag.
+ *
+ * This code accesses the X509_CRL structure directly:
+ * applications shouldn't do this.
+ */
+
+ exts = crl->crl->extensions;
+
+ for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
+ {
+ int nid;
+ ext = sk_X509_EXTENSION_value(exts, idx);
+ nid = OBJ_obj2nid(ext->object);
+ if (nid == NID_freshest_crl)
+ crl->flags |= EXFLAG_FRESHEST;
+ if (ext->critical > 0)
+ {
+ /* We handle IDP and deltas */
+ if ((nid == NID_issuing_distribution_point)
+ || (nid == NID_authority_key_identifier)
+ || (nid == NID_delta_crl))
+ break;;
+ crl->flags |= EXFLAG_CRITICAL;
+ break;
+ }
+ }
+
+
+ if (!crl_set_issuers(crl))
+ return 0;
+
+ if (crl->meth->crl_init)
+ {
+ if (crl->meth->crl_init(crl) == 0)
+ return 0;
+ }
+ break;
+
+ case ASN1_OP_FREE_POST:
+ if (crl->meth->crl_free)
+ {
+ if (!crl->meth->crl_free(crl))
+ return 0;
+ }
+ if (crl->akid)
+ AUTHORITY_KEYID_free(crl->akid);
+ if (crl->idp)
+ ISSUING_DIST_POINT_free(crl->idp);
+ ASN1_INTEGER_free(crl->crl_number);
+ ASN1_INTEGER_free(crl->base_crl_number);
+ sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
+ break;
+ }
+ return 1;
+ }
+
+/* Convert IDP into a more convenient form */
+
+static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
+ {
+ int idp_only = 0;
+ /* Set various flags according to IDP */
+ crl->idp_flags |= IDP_PRESENT;
+ if (idp->onlyuser > 0)
+ {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYUSER;
+ }
+ if (idp->onlyCA > 0)
+ {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYCA;
+ }
+ if (idp->onlyattr > 0)
+ {
+ idp_only++;
+ crl->idp_flags |= IDP_ONLYATTR;
+ }
+
+ if (idp_only > 1)
+ crl->idp_flags |= IDP_INVALID;
+
+ if (idp->indirectCRL > 0)
+ crl->idp_flags |= IDP_INDIRECT;
+
+ if (idp->onlysomereasons)
+ {
+ crl->idp_flags |= IDP_REASONS;
+ if (idp->onlysomereasons->length > 0)
+ crl->idp_reasons = idp->onlysomereasons->data[0];
+ if (idp->onlysomereasons->length > 1)
+ crl->idp_reasons |=
+ (idp->onlysomereasons->data[1] << 8);
+ crl->idp_reasons &= CRLDP_ALL_REASONS;
+ }
+
+ DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
+ }
+
+ASN1_SEQUENCE_ref(X509_CRL, crl_cb, CRYPTO_LOCK_X509_CRL) = {
+ ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
+ ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
+IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
+IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
+
+static int X509_REVOKED_cmp(const X509_REVOKED **a,
+ const X509_REVOKED **b)
+ {
+ return(ASN1_STRING_cmp(
+ (ASN1_STRING *)(*a)->serialNumber,
+ (ASN1_STRING *)(*b)->serialNumber));
+ }
+
+int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
+{
+ X509_CRL_INFO *inf;
+ inf = crl->crl;
+ if(!inf->revoked)
+ inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
+ if(!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
+ OPENSSL_PUT_ERROR(X509, X509_CRL_add0_revoked, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ inf->enc.modified = 1;
+ return 1;
+}
+
+int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
+ {
+ if (crl->meth->crl_verify)
+ return crl->meth->crl_verify(crl, r);
+ return 0;
+ }
+
+int X509_CRL_get0_by_serial(X509_CRL *crl,
+ X509_REVOKED **ret, ASN1_INTEGER *serial)
+ {
+ if (crl->meth->crl_lookup)
+ return crl->meth->crl_lookup(crl, ret, serial, NULL);
+ return 0;
+ }
+
+int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
+ {
+ if (crl->meth->crl_lookup)
+ return crl->meth->crl_lookup(crl, ret,
+ X509_get_serialNumber(x),
+ X509_get_issuer_name(x));
+ return 0;
+ }
+
+static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
+ {
+ return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
+ crl->sig_alg, crl->signature,crl->crl,r));
+ }
+
+static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
+ X509_REVOKED *rev)
+ {
+ size_t i;
+
+ if (!rev->issuer)
+ {
+ if (!nm)
+ return 1;
+ if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
+ return 1;
+ return 0;
+ }
+
+ if (!nm)
+ nm = X509_CRL_get_issuer(crl);
+
+ for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++)
+ {
+ GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
+ if (gen->type != GEN_DIRNAME)
+ continue;
+ if (!X509_NAME_cmp(nm, gen->d.directoryName))
+ return 1;
+ }
+ return 0;
+
+ }
+
+static int def_crl_lookup(X509_CRL *crl,
+ X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer)
+ {
+ X509_REVOKED rtmp, *rev;
+ size_t idx;
+ rtmp.serialNumber = serial;
+ /* Sort revoked into serial number order if not already sorted.
+ * Do this under a lock to avoid race condition.
+ */
+ if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
+ {
+ CRYPTO_w_lock(CRYPTO_LOCK_X509_CRL);
+ sk_X509_REVOKED_sort(crl->crl->revoked);
+ CRYPTO_w_unlock(CRYPTO_LOCK_X509_CRL);
+ }
+ if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
+ return 0;
+ /* Need to look for matching name */
+ for(;idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++)
+ {
+ rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
+ if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
+ return 0;
+ if (crl_revoked_issuer_match(crl, issuer, rev))
+ {
+ if (ret)
+ *ret = rev;
+ if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+ return 2;
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+void X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
+ {
+ if (meth == NULL)
+ default_crl_method = &int_crl_meth;
+ else
+ default_crl_method = meth;
+ }
+
+X509_CRL_METHOD *X509_CRL_METHOD_new(
+ int (*crl_init)(X509_CRL *crl),
+ int (*crl_free)(X509_CRL *crl),
+ int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
+ ASN1_INTEGER *ser, X509_NAME *issuer),
+ int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk))
+ {
+ X509_CRL_METHOD *m;
+ m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
+ if (!m)
+ return NULL;
+ m->crl_init = crl_init;
+ m->crl_free = crl_free;
+ m->crl_lookup = crl_lookup;
+ m->crl_verify = crl_verify;
+ m->flags = X509_CRL_METHOD_DYNAMIC;
+ return m;
+ }
+
+void X509_CRL_METHOD_free(X509_CRL_METHOD *m)
+ {
+ if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
+ return;
+ OPENSSL_free(m);
+ }
+
+void X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
+ {
+ crl->meth_data = dat;
+ }
+
+void *X509_CRL_get_meth_data(X509_CRL *crl)
+ {
+ return crl->meth_data;
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
+IMPLEMENT_ASN1_SET_OF(X509_CRL)
diff --git a/src/crypto/x509/x_exten.c b/src/crypto/x509/x_exten.c
new file mode 100644
index 0000000..cf64c84
--- /dev/null
+++ b/src/crypto/x509/x_exten.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/cipher.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_EXTENSION) = {
+ ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
+ ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
+ ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(X509_EXTENSION)
+
+ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
+ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(X509_EXTENSIONS, X509_EXTENSIONS, X509_EXTENSIONS)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_EXTENSION)
diff --git a/src/crypto/x509/x_info.c b/src/crypto/x509/x_info.c
new file mode 100644
index 0000000..8047c71
--- /dev/null
+++ b/src/crypto/x509/x_info.c
@@ -0,0 +1,110 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+X509_INFO *X509_INFO_new(void)
+ {
+ X509_INFO *ret=NULL;
+
+ ret=(X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_INFO_new, ERR_R_MALLOC_FAILURE);
+ return(NULL);
+ }
+
+ ret->enc_cipher.cipher=NULL;
+ ret->enc_len=0;
+ ret->enc_data=NULL;
+
+ ret->references=1;
+ ret->x509=NULL;
+ ret->crl=NULL;
+ ret->x_pkey=NULL;
+ return(ret);
+ }
+
+void X509_INFO_free(X509_INFO *x)
+ {
+ int i;
+
+ if (x == NULL) return;
+
+ i=CRYPTO_add(&x->references,-1,CRYPTO_LOCK_X509_INFO);
+#ifdef REF_PRINT
+ REF_PRINT("X509_INFO",x);
+#endif
+ if (i > 0) return;
+#ifdef REF_CHECK
+ if (i < 0)
+ {
+ fprintf(stderr,"X509_INFO_free, bad reference count\n");
+ abort();
+ }
+#endif
+
+ if (x->x509 != NULL) X509_free(x->x509);
+ if (x->crl != NULL) X509_CRL_free(x->crl);
+ if (x->x_pkey != NULL) X509_PKEY_free(x->x_pkey);
+ if (x->enc_data != NULL) OPENSSL_free(x->enc_data);
+ OPENSSL_free(x);
+ }
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
new file mode 100644
index 0000000..211f68f
--- /dev/null
+++ b/src/crypto/x509/x_name.c
@@ -0,0 +1,533 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <ctype.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/buf.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+#include "../asn1/asn1_locl.h"
+
+
+typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
+DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
+
+static int x509_name_ex_d2i(ASN1_VALUE **val,
+ const unsigned char **in, long len,
+ const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx);
+
+static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
+ const ASN1_ITEM *it, int tag, int aclass);
+static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
+static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
+
+static int x509_name_encode(X509_NAME *a);
+static int x509_name_canon(X509_NAME *a);
+static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
+ unsigned char **in);
+
+
+static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
+ int indent,
+ const char *fname,
+ const ASN1_PCTX *pctx);
+
+ASN1_SEQUENCE(X509_NAME_ENTRY) = {
+ ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
+ ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
+} ASN1_SEQUENCE_END(X509_NAME_ENTRY)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
+
+/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
+ * so declare two template wrappers for this
+ */
+
+ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
+ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES)
+
+ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) =
+ ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
+ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
+
+/* Normally that's where it would end: we'd have two nested STACK structures
+ * representing the ASN1. Unfortunately X509_NAME uses a completely different
+ * form and caches encodings so we have to process the internal form and convert
+ * to the external form.
+ */
+
+const ASN1_EXTERN_FUNCS x509_name_ff = {
+ NULL,
+ x509_name_ex_new,
+ x509_name_ex_free,
+ 0, /* Default clear behaviour is OK */
+ x509_name_ex_d2i,
+ x509_name_ex_i2d,
+ x509_name_ex_print
+};
+
+IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_NAME)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME)
+
+static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
+{
+ X509_NAME *ret = NULL;
+ ret = OPENSSL_malloc(sizeof(X509_NAME));
+ if(!ret) goto memerr;
+ if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL)
+ goto memerr;
+ if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr;
+ ret->canon_enc = NULL;
+ ret->canon_enclen = 0;
+ ret->modified=1;
+ *val = (ASN1_VALUE *)ret;
+ return 1;
+
+ memerr:
+ OPENSSL_PUT_ERROR(X509, x509_name_ex_new, ERR_R_MALLOC_FAILURE);
+ if (ret)
+ {
+ if (ret->entries)
+ sk_X509_NAME_ENTRY_free(ret->entries);
+ OPENSSL_free(ret);
+ }
+ return 0;
+}
+
+static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
+{
+ X509_NAME *a;
+ if(!pval || !*pval)
+ return;
+ a = (X509_NAME *)*pval;
+
+ BUF_MEM_free(a->bytes);
+ sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free);
+ if (a->canon_enc)
+ OPENSSL_free(a->canon_enc);
+ OPENSSL_free(a);
+ *pval = NULL;
+}
+
+static int x509_name_ex_d2i(ASN1_VALUE **val,
+ const unsigned char **in, long len, const ASN1_ITEM *it,
+ int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+ const unsigned char *p = *in, *q;
+ union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+ ASN1_VALUE *a; } intname = {NULL};
+ union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL};
+ size_t i, j;
+ int ret;
+ STACK_OF(X509_NAME_ENTRY) *entries;
+ X509_NAME_ENTRY *entry;
+ q = p;
+
+ /* Get internal representation of Name */
+ ret = ASN1_item_ex_d2i(&intname.a,
+ &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
+ tag, aclass, opt, ctx);
+
+ if(ret <= 0) return ret;
+
+ if(*val) x509_name_ex_free(val, NULL);
+ if(!x509_name_ex_new(&nm.a, NULL)) goto err;
+ /* We've decoded it: now cache encoding */
+ if(!BUF_MEM_grow(nm.x->bytes, p - q)) goto err;
+ memcpy(nm.x->bytes->data, q, p - q);
+
+ /* Convert internal representation to X509_NAME structure */
+ for(i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
+ entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
+ for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
+ entry = sk_X509_NAME_ENTRY_value(entries, j);
+ entry->set = i;
+ if(!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
+ goto err;
+ }
+ sk_X509_NAME_ENTRY_free(entries);
+ }
+ sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
+ ret = x509_name_canon(nm.x);
+ if (!ret)
+ goto err;
+ nm.x->modified = 0;
+ *val = nm.a;
+ *in = p;
+ return ret;
+err:
+ if (nm.x != NULL)
+ X509_NAME_free(nm.x);
+ OPENSSL_PUT_ERROR(X509, x509_name_ex_d2i, ERR_R_ASN1_LIB);
+ return 0;
+}
+
+static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
+{
+ int ret;
+ X509_NAME *a = (X509_NAME *)*val;
+ if(a->modified) {
+ ret = x509_name_encode(a);
+ if(ret < 0)
+ return ret;
+ ret = x509_name_canon(a);
+ if(ret < 0)
+ return ret;
+ }
+ ret = a->bytes->length;
+ if(out != NULL) {
+ memcpy(*out,a->bytes->data,ret);
+ *out+=ret;
+ }
+ return ret;
+}
+
+static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
+ {
+ sk_X509_NAME_ENTRY_free(ne);
+ }
+
+static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
+ {
+ sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+ }
+
+static int x509_name_encode(X509_NAME *a)
+{
+ union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+ ASN1_VALUE *a; } intname = {NULL};
+ int len;
+ unsigned char *p;
+ STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+ X509_NAME_ENTRY *entry;
+ int set = -1;
+ size_t i;
+ intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+ if(!intname.s) goto memerr;
+ for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+ entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+ if(entry->set != set) {
+ entries = sk_X509_NAME_ENTRY_new_null();
+ if(!entries) goto memerr;
+ if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s,
+ entries))
+ goto memerr;
+ set = entry->set;
+ }
+ if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr;
+ }
+ len = ASN1_item_ex_i2d(&intname.a, NULL,
+ ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+ if (!BUF_MEM_grow(a->bytes,len)) goto memerr;
+ p=(unsigned char *)a->bytes->data;
+ ASN1_item_ex_i2d(&intname.a,
+ &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_free);
+ a->modified = 0;
+ return len;
+memerr:
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+ local_sk_X509_NAME_ENTRY_free);
+ OPENSSL_PUT_ERROR(X509, x509_name_encode, ERR_R_MALLOC_FAILURE);
+ return -1;
+}
+
+static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
+ int indent,
+ const char *fname,
+ const ASN1_PCTX *pctx)
+ {
+ if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
+ indent, pctx->nm_flags) <= 0)
+ return 0;
+ return 2;
+ }
+
+/* This function generates the canonical encoding of the Name structure.
+ * In it all strings are converted to UTF8, leading, trailing and
+ * multiple spaces collapsed, converted to lower case and the leading
+ * SEQUENCE header removed.
+ *
+ * In future we could also normalize the UTF8 too.
+ *
+ * By doing this comparison of Name structures can be rapidly
+ * perfomed by just using memcmp() of the canonical encoding.
+ * By omitting the leading SEQUENCE name constraints of type
+ * dirName can also be checked with a simple memcmp().
+ */
+
+static int x509_name_canon(X509_NAME *a)
+ {
+ unsigned char *p;
+ STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+ STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+ X509_NAME_ENTRY *entry, *tmpentry = NULL;
+ int set = -1, ret = 0;
+ size_t i;
+
+ if (a->canon_enc)
+ {
+ OPENSSL_free(a->canon_enc);
+ a->canon_enc = NULL;
+ }
+ /* Special case: empty X509_NAME => null encoding */
+ if (sk_X509_NAME_ENTRY_num(a->entries) == 0)
+ {
+ a->canon_enclen = 0;
+ return 1;
+ }
+ intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+ if(!intname)
+ goto err;
+ for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++)
+ {
+ entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+ if(entry->set != set)
+ {
+ entries = sk_X509_NAME_ENTRY_new_null();
+ if(!entries)
+ goto err;
+ if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
+ {
+ sk_X509_NAME_ENTRY_free(entries);
+ goto err;
+ }
+ set = entry->set;
+ }
+ tmpentry = X509_NAME_ENTRY_new();
+ if (tmpentry == NULL)
+ goto err;
+ tmpentry->object = OBJ_dup(entry->object);
+ if (!asn1_string_canon(tmpentry->value, entry->value))
+ goto err;
+ if(!sk_X509_NAME_ENTRY_push(entries, tmpentry))
+ goto err;
+ tmpentry = NULL;
+ }
+
+ /* Finally generate encoding */
+
+ a->canon_enclen = i2d_name_canon(intname, NULL);
+
+ p = OPENSSL_malloc(a->canon_enclen);
+
+ if (!p)
+ goto err;
+
+ a->canon_enc = p;
+
+ i2d_name_canon(intname, &p);
+
+ ret = 1;
+
+ err:
+
+ if (tmpentry)
+ X509_NAME_ENTRY_free(tmpentry);
+ if (intname)
+ sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
+ local_sk_X509_NAME_ENTRY_pop_free);
+ return ret;
+ }
+
+/* Bitmap of all the types of string that will be canonicalized. */
+
+#define ASN1_MASK_CANON \
+ (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
+ | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
+ | B_ASN1_VISIBLESTRING)
+
+
+static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
+ {
+ unsigned char *to, *from;
+ int len, i;
+
+ /* If type not in bitmask just copy string across */
+ if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON))
+ {
+ if (!ASN1_STRING_copy(out, in))
+ return 0;
+ return 1;
+ }
+
+ out->type = V_ASN1_UTF8STRING;
+ out->length = ASN1_STRING_to_UTF8(&out->data, in);
+ if (out->length == -1)
+ return 0;
+
+ to = out->data;
+ from = to;
+
+ len = out->length;
+
+ /* Convert string in place to canonical form.
+ * Ultimately we may need to handle a wider range of characters
+ * but for now ignore anything with MSB set and rely on the
+ * isspace() and tolower() functions.
+ */
+
+ /* Ignore leading spaces */
+ while((len > 0) && !(*from & 0x80) && isspace(*from))
+ {
+ from++;
+ len--;
+ }
+
+ to = from + len - 1;
+
+ /* Ignore trailing spaces */
+ while ((len > 0) && !(*to & 0x80) && isspace(*to))
+ {
+ to--;
+ len--;
+ }
+
+ to = out->data;
+
+ i = 0;
+ while(i < len)
+ {
+ /* If MSB set just copy across */
+ if (*from & 0x80)
+ {
+ *to++ = *from++;
+ i++;
+ }
+ /* Collapse multiple spaces */
+ else if (isspace(*from))
+ {
+ /* Copy one space across */
+ *to++ = ' ';
+ /* Ignore subsequent spaces. Note: don't need to
+ * check len here because we know the last
+ * character is a non-space so we can't overflow.
+ */
+ do
+ {
+ from++;
+ i++;
+ }
+ while(!(*from & 0x80) && isspace(*from));
+ }
+ else
+ {
+ *to++ = tolower(*from);
+ from++;
+ i++;
+ }
+ }
+
+ out->length = to - out->data;
+
+ return 1;
+
+ }
+
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname,
+ unsigned char **in)
+ {
+ int len, ltmp;
+ size_t i;
+ ASN1_VALUE *v;
+ STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
+
+ len = 0;
+ for (i = 0; i < sk_ASN1_VALUE_num(intname); i++)
+ {
+ v = sk_ASN1_VALUE_value(intname, i);
+ ltmp = ASN1_item_ex_i2d(&v, in,
+ ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
+ if (ltmp < 0)
+ return ltmp;
+ len += ltmp;
+ }
+ return len;
+ }
+
+int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
+ {
+ X509_NAME *in;
+
+ if (!xn || !name) return(0);
+
+ if (*xn != name)
+ {
+ in=X509_NAME_dup(name);
+ if (in != NULL)
+ {
+ X509_NAME_free(*xn);
+ *xn=in;
+ }
+ }
+ return(*xn != NULL);
+ }
+
+IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
diff --git a/src/crypto/x509/x_pkey.c b/src/crypto/x509/x_pkey.c
new file mode 100644
index 0000000..550078b
--- /dev/null
+++ b/src/crypto/x509/x_pkey.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/x509.h>
+
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/mem.h>
+#include <openssl/err.h>
+
+
+X509_PKEY *X509_PKEY_new(void)
+ {
+ X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
+ if (ret == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PKEY_new, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ memset(ret, 0, sizeof(X509_PKEY));
+ ret->references=1;
+
+ ret->enc_algor = X509_ALGOR_new();
+ if (ret->enc_algor == NULL)
+ goto err;
+ ret->enc_pkey = M_ASN1_OCTET_STRING_new();
+ if (ret->enc_pkey == NULL)
+ goto err;
+ return ret;
+
+err:
+ if (ret != NULL)
+ X509_PKEY_free(ret);
+ return NULL;
+ }
+
+void X509_PKEY_free(X509_PKEY *x)
+ {
+ int i;
+
+ if (x == NULL) return;
+
+ i=CRYPTO_add(&x->references,-1,CRYPTO_LOCK_X509_PKEY);
+ if (i > 0) return;
+
+ if (x->enc_algor != NULL) X509_ALGOR_free(x->enc_algor);
+ if (x->enc_pkey != NULL) M_ASN1_OCTET_STRING_free(x->enc_pkey);
+ if (x->dec_pkey != NULL)EVP_PKEY_free(x->dec_pkey);
+ if ((x->key_data != NULL) && (x->key_free)) OPENSSL_free(x->key_data);
+ OPENSSL_free(x);
+ }
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
new file mode 100644
index 0000000..c285aa6
--- /dev/null
+++ b/src/crypto/x509/x_pubkey.c
@@ -0,0 +1,373 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+#include "../evp/internal.h"
+
+
+/* Minor tweak to operation: free up EVP_PKEY */
+static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+ {
+ if (operation == ASN1_OP_FREE_POST)
+ {
+ X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
+ EVP_PKEY_free(pubkey->pkey);
+ }
+ return 1;
+ }
+
+ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
+ ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
+
+int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
+ {
+ X509_PUBKEY *pk=NULL;
+
+ if (x == NULL) return(0);
+
+ if ((pk=X509_PUBKEY_new()) == NULL) goto error;
+
+ if (pkey->ameth)
+ {
+ if (pkey->ameth->pub_encode)
+ {
+ if (!pkey->ameth->pub_encode(pk, pkey))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_PUBLIC_KEY_ENCODE_ERROR);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_set, X509_R_UNSUPPORTED_ALGORITHM);
+ goto error;
+ }
+
+ if (*x != NULL)
+ X509_PUBKEY_free(*x);
+
+ *x=pk;
+
+ return 1;
+error:
+ if (pk != NULL) X509_PUBKEY_free(pk);
+ return 0;
+ }
+
+EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
+ {
+ EVP_PKEY *ret=NULL;
+
+ if (key == NULL) goto error;
+
+ if (key->pkey != NULL)
+ {
+ return EVP_PKEY_dup(key->pkey);
+ }
+
+ if (key->public_key == NULL) goto error;
+
+ if ((ret = EVP_PKEY_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, ERR_R_MALLOC_FAILURE);
+ goto error;
+ }
+
+ if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_UNSUPPORTED_ALGORITHM);
+ goto error;
+ }
+
+ if (ret->ameth->pub_decode)
+ {
+ if (!ret->ameth->pub_decode(ret, key))
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_PUBLIC_KEY_DECODE_ERROR);
+ goto error;
+ }
+ }
+ else
+ {
+ OPENSSL_PUT_ERROR(X509, X509_PUBKEY_get, X509_R_METHOD_NOT_SUPPORTED);
+ goto error;
+ }
+
+ /* Check to see if another thread set key->pkey first */
+ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
+ if (key->pkey)
+ {
+ CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+ EVP_PKEY_free(ret);
+ ret = key->pkey;
+ }
+ else
+ {
+ key->pkey = ret;
+ CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
+ }
+
+ return EVP_PKEY_dup(ret);
+
+ error:
+ if (ret != NULL)
+ EVP_PKEY_free(ret);
+ return(NULL);
+ }
+
+/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
+ * and encode or decode as X509_PUBKEY
+ */
+
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
+ long length)
+ {
+ X509_PUBKEY *xpk;
+ EVP_PKEY *pktmp;
+ xpk = d2i_X509_PUBKEY(NULL, pp, length);
+ if(!xpk) return NULL;
+ pktmp = X509_PUBKEY_get(xpk);
+ X509_PUBKEY_free(xpk);
+ if(!pktmp) return NULL;
+ if(a)
+ {
+ EVP_PKEY_free(*a);
+ *a = pktmp;
+ }
+ return pktmp;
+ }
+
+int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
+ {
+ X509_PUBKEY *xpk=NULL;
+ int ret;
+ if(!a) return 0;
+ if(!X509_PUBKEY_set(&xpk, (EVP_PKEY*) a)) return 0;
+ ret = i2d_X509_PUBKEY(xpk, pp);
+ X509_PUBKEY_free(xpk);
+ return ret;
+ }
+
+/* The following are equivalents but which return RSA and DSA
+ * keys
+ */
+RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
+ long length)
+ {
+ EVP_PKEY *pkey;
+ RSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return NULL;
+ key = EVP_PKEY_get1_RSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return NULL;
+ *pp = q;
+ if (a)
+ {
+ RSA_free(*a);
+ *a = key;
+ }
+ return key;
+ }
+
+int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a) return 0;
+ pktmp = EVP_PKEY_new();
+ if (!pktmp)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_RSA(pktmp, (RSA*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+ }
+
+#ifndef OPENSSL_NO_DSA
+DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
+ long length)
+ {
+ EVP_PKEY *pkey;
+ DSA *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return NULL;
+ key = EVP_PKEY_get1_DSA(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return NULL;
+ *pp = q;
+ if (a)
+ {
+ DSA_free(*a);
+ *a = key;
+ }
+ return key;
+ }
+
+int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if(!a) return 0;
+ pktmp = EVP_PKEY_new();
+ if(!pktmp)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ EVP_PKEY_set1_DSA(pktmp, (DSA*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return ret;
+ }
+#endif
+
+EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
+ {
+ EVP_PKEY *pkey;
+ EC_KEY *key;
+ const unsigned char *q;
+ q = *pp;
+ pkey = d2i_PUBKEY(NULL, &q, length);
+ if (!pkey) return(NULL);
+ key = EVP_PKEY_get1_EC_KEY(pkey);
+ EVP_PKEY_free(pkey);
+ if (!key) return(NULL);
+ *pp = q;
+ if (a)
+ {
+ EC_KEY_free(*a);
+ *a = key;
+ }
+ return(key);
+ }
+
+int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
+ {
+ EVP_PKEY *pktmp;
+ int ret;
+ if (!a) return(0);
+ if ((pktmp = EVP_PKEY_new()) == NULL)
+ {
+ OPENSSL_PUT_ERROR(X509, i2d_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
+ return(0);
+ }
+ EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY*) a);
+ ret = i2d_PUBKEY(pktmp, pp);
+ EVP_PKEY_free(pktmp);
+ return(ret);
+ }
+
+int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
+ int ptype, void *pval,
+ unsigned char *penc, int penclen)
+ {
+ if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
+ return 0;
+ if (penc)
+ {
+ if (pub->public_key->data)
+ OPENSSL_free(pub->public_key->data);
+ pub->public_key->data = penc;
+ pub->public_key->length = penclen;
+ /* Set number of unused bits to zero */
+ pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
+ pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
+ }
+ return 1;
+ }
+
+int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
+ const unsigned char **pk, int *ppklen,
+ X509_ALGOR **pa,
+ X509_PUBKEY *pub)
+ {
+ if (ppkalg)
+ *ppkalg = pub->algor->algorithm;
+ if (pk)
+ {
+ *pk = pub->public_key->data;
+ *ppklen = pub->public_key->length;
+ }
+ if (pa)
+ *pa = pub->algor;
+ return 1;
+ }
diff --git a/src/crypto/x509/x_req.c b/src/crypto/x509/x_req.c
new file mode 100644
index 0000000..8bf4613
--- /dev/null
+++ b/src/crypto/x509/x_req.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/thread.h>
+#include <openssl/x509.h>
+
+/* X509_REQ_INFO is handled in an unusual way to get round
+ * invalid encodings. Some broken certificate requests don't
+ * encode the attributes field if it is empty. This is in
+ * violation of PKCS#10 but we need to tolerate it. We do
+ * this by making the attributes field OPTIONAL then using
+ * the callback to initialise it to an empty STACK.
+ *
+ * This means that the field will be correctly encoded unless
+ * we NULL out the field.
+ *
+ * As a result we no longer need the req_kludge field because
+ * the information is now contained in the attributes field:
+ * 1. If it is NULL then it's the invalid omission.
+ * 2. If it is empty it is the correct encoding.
+ * 3. If it is not empty then some attributes are present.
+ *
+ */
+
+static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
+
+ if(operation == ASN1_OP_NEW_POST) {
+ rinf->attributes = sk_X509_ATTRIBUTE_new_null();
+ if(!rinf->attributes) return 0;
+ }
+ return 1;
+}
+
+ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
+ ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
+ ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
+ /* This isn't really OPTIONAL but it gets round invalid
+ * encodings
+ */
+ ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
+
+ASN1_SEQUENCE_ref(X509_REQ, 0, CRYPTO_LOCK_X509_REQ) = {
+ ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
+ ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
diff --git a/src/crypto/x509/x_sig.c b/src/crypto/x509/x_sig.c
new file mode 100644
index 0000000..fabdb67
--- /dev/null
+++ b/src/crypto/x509/x_sig.c
@@ -0,0 +1,69 @@
+/* crypto/asn1/x_sig.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_SIG) = {
+ ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
+ ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
+} ASN1_SEQUENCE_END(X509_SIG)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
diff --git a/src/crypto/x509/x_spki.c b/src/crypto/x509/x_spki.c
new file mode 100644
index 0000000..35bf246
--- /dev/null
+++ b/src/crypto/x509/x_spki.c
@@ -0,0 +1,78 @@
+/* crypto/asn1/x_spki.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+ /* This module was send to me my Pat Richards <patr@x509.com> who
+ * wrote it. It is under my Copyright with his permission. */
+
+#include <openssl/x509.h>
+#include <openssl/asn1t.h>
+
+
+ASN1_SEQUENCE(NETSCAPE_SPKAC) = {
+ ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
+ ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
+} ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
+
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
+
+ASN1_SEQUENCE(NETSCAPE_SPKI) = {
+ ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
+ ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
+ ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(NETSCAPE_SPKI)
+
+IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
diff --git a/src/crypto/x509/x_val.c b/src/crypto/x509/x_val.c
new file mode 100644
index 0000000..26200ee
--- /dev/null
+++ b/src/crypto/x509/x_val.c
@@ -0,0 +1,69 @@
+/* crypto/asn1/x_val.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/x509.h>
+
+
+ASN1_SEQUENCE(X509_VAL) = {
+ ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
+ ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
+} ASN1_SEQUENCE_END(X509_VAL)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
new file mode 100644
index 0000000..5cda3c7
--- /dev/null
+++ b/src/crypto/x509/x_x509.c
@@ -0,0 +1,209 @@
+/* crypto/asn1/x_x509.c */
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 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 acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS 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 AUTHOR OR 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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/obj.h>
+#include <openssl/thread.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+
+ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
+ ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
+ ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
+ ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
+ ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
+ ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
+ ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
+ ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
+ ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
+ ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
+} ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
+/* X509 top level structure needs a bit of customisation */
+
+extern void policy_cache_free(X509_POLICY_CACHE *cache);
+
+static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+ void *exarg)
+{
+ X509 *ret = (X509 *)*pval;
+
+ switch(operation) {
+
+ case ASN1_OP_NEW_POST:
+ ret->valid=0;
+ ret->name = NULL;
+ ret->ex_flags = 0;
+ ret->ex_pathlen = -1;
+ ret->skid = NULL;
+ ret->akid = NULL;
+ ret->aux = NULL;
+ ret->crldp = NULL;
+ CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+ break;
+
+ case ASN1_OP_D2I_POST:
+ if (ret->name != NULL) OPENSSL_free(ret->name);
+ ret->name=X509_NAME_oneline(ret->cert_info->subject,NULL,0);
+ break;
+
+ case ASN1_OP_FREE_POST:
+ CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509, ret, &ret->ex_data);
+ X509_CERT_AUX_free(ret->aux);
+ ASN1_OCTET_STRING_free(ret->skid);
+ AUTHORITY_KEYID_free(ret->akid);
+ CRL_DIST_POINTS_free(ret->crldp);
+ policy_cache_free(ret->policy_cache);
+ GENERAL_NAMES_free(ret->altname);
+ NAME_CONSTRAINTS_free(ret->nc);
+
+ if (ret->name != NULL) OPENSSL_free(ret->name);
+ break;
+
+ }
+
+ return 1;
+
+}
+
+ASN1_SEQUENCE_ref(X509, x509_cb, CRYPTO_LOCK_X509) = {
+ ASN1_SIMPLE(X509, cert_info, X509_CINF),
+ ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
+ ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END_ref(X509, X509)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509)
+IMPLEMENT_ASN1_DUP_FUNCTION(X509)
+
+X509 *X509_up_ref(X509 *x)
+ {
+ CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509);
+ return x;
+ }
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
+ CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+ {
+ return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509, argl, argp,
+ new_func, dup_func, free_func);
+ }
+
+int X509_set_ex_data(X509 *r, int idx, void *arg)
+ {
+ return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
+ }
+
+void *X509_get_ex_data(X509 *r, int idx)
+ {
+ return(CRYPTO_get_ex_data(&r->ex_data,idx));
+ }
+
+/* X509_AUX ASN1 routines. X509_AUX is the name given to
+ * a certificate with extra info tagged on the end. Since these
+ * functions set how a certificate is trusted they should only
+ * be used when the certificate comes from a reliable source
+ * such as local storage.
+ *
+ */
+
+X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
+{
+ const unsigned char *q;
+ X509 *ret;
+ /* Save start position */
+ q = *pp;
+ ret = d2i_X509(a, pp, length);
+ /* If certificate unreadable then forget it */
+ if(!ret) return NULL;
+ /* update length */
+ length -= *pp - q;
+ if(!length) return ret;
+ if(!d2i_X509_CERT_AUX(&ret->aux, pp, length)) goto err;
+ return ret;
+ err:
+ X509_free(ret);
+ return NULL;
+}
+
+int i2d_X509_AUX(X509 *a, unsigned char **pp)
+{
+ int length;
+ length = i2d_X509(a, pp);
+ if(a) length += i2d_X509_CERT_AUX(a->aux, pp);
+ return length;
+}
+
+void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
+ const X509 *x)
+ {
+ if (psig)
+ *psig = x->signature;
+ if (palg)
+ *palg = x->sig_alg;
+ }
+
+int X509_get_signature_nid(const X509 *x)
+ {
+ return OBJ_obj2nid(x->sig_alg->algorithm);
+ }
diff --git a/src/crypto/x509/x_x509a.c b/src/crypto/x509/x_x509a.c
new file mode 100644
index 0000000..e13204b
--- /dev/null
+++ b/src/crypto/x509/x_x509a.c
@@ -0,0 +1,177 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999. */
+/* ====================================================================
+ * Copyright (c) 1999 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 <stdio.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/x509.h>
+
+
+/* X509_CERT_AUX routines. These are used to encode additional
+ * user modifiable data about a certificate. This data is
+ * appended to the X509 encoding when the *_X509_AUX routines
+ * are used. This means that the "traditional" X509 routines
+ * will simply ignore the extra data. */
+
+static X509_CERT_AUX *aux_get(X509 *x);
+
+ASN1_SEQUENCE(X509_CERT_AUX) = {
+ ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
+ ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
+ ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
+ ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
+} ASN1_SEQUENCE_END(X509_CERT_AUX)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
+
+static X509_CERT_AUX *aux_get(X509 *x)
+{
+ if(!x) return NULL;
+ if(!x->aux && !(x->aux = X509_CERT_AUX_new())) return NULL;
+ return x->aux;
+}
+
+int X509_alias_set1(X509 *x, unsigned char *name, int len)
+{
+ X509_CERT_AUX *aux;
+ if (!name)
+ {
+ if (!x || !x->aux || !x->aux->alias)
+ return 1;
+ ASN1_UTF8STRING_free(x->aux->alias);
+ x->aux->alias = NULL;
+ return 1;
+ }
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0;
+ return ASN1_STRING_set(aux->alias, name, len);
+}
+
+int X509_keyid_set1(X509 *x, unsigned char *id, int len)
+{
+ X509_CERT_AUX *aux;
+ if (!id)
+ {
+ if (!x || !x->aux || !x->aux->keyid)
+ return 1;
+ ASN1_OCTET_STRING_free(x->aux->keyid);
+ x->aux->keyid = NULL;
+ return 1;
+ }
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
+ return ASN1_STRING_set(aux->keyid, id, len);
+}
+
+unsigned char *X509_alias_get0(X509 *x, int *len)
+{
+ if(!x->aux || !x->aux->alias) return NULL;
+ if(len) *len = x->aux->alias->length;
+ return x->aux->alias->data;
+}
+
+unsigned char *X509_keyid_get0(X509 *x, int *len)
+{
+ if(!x->aux || !x->aux->keyid) return NULL;
+ if(len) *len = x->aux->keyid->length;
+ return x->aux->keyid->data;
+}
+
+int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj)
+{
+ X509_CERT_AUX *aux;
+ ASN1_OBJECT *objtmp;
+ if(!(objtmp = OBJ_dup(obj))) return 0;
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->trust
+ && !(aux->trust = sk_ASN1_OBJECT_new_null())) return 0;
+ return sk_ASN1_OBJECT_push(aux->trust, objtmp);
+}
+
+int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj)
+{
+ X509_CERT_AUX *aux;
+ ASN1_OBJECT *objtmp;
+ if(!(objtmp = OBJ_dup(obj))) return 0;
+ if(!(aux = aux_get(x))) return 0;
+ if(!aux->reject
+ && !(aux->reject = sk_ASN1_OBJECT_new_null())) return 0;
+ return sk_ASN1_OBJECT_push(aux->reject, objtmp);
+}
+
+void X509_trust_clear(X509 *x)
+{
+ if(x->aux && x->aux->trust) {
+ sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
+ x->aux->trust = NULL;
+ }
+}
+
+void X509_reject_clear(X509 *x)
+{
+ if(x->aux && x->aux->reject) {
+ sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
+ x->aux->reject = NULL;
+ }
+}
+
+ASN1_SEQUENCE(X509_CERT_PAIR) = {
+ ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
+ ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
+} ASN1_SEQUENCE_END(X509_CERT_PAIR)
+
+IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_PAIR)