diff options
| author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 | 
|---|---|---|
| committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 | 
| commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
| tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /openssl-1.1.0h/crypto/asn1 | |
| download | smtps-and-pop3s-console-program-master.tar.gz smtps-and-pop3s-console-program-master.zip | |
Diffstat (limited to 'openssl-1.1.0h/crypto/asn1')
67 files changed, 14770 insertions, 0 deletions
| diff --git a/openssl-1.1.0h/crypto/asn1/a_bitstr.c b/openssl-1.1.0h/crypto/asn1/a_bitstr.c new file mode 100644 index 0000000..b2e0fb6 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_bitstr.c @@ -0,0 +1,216 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <limits.h> +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include "asn1_locl.h" + +int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len) +{ +    return ASN1_STRING_set(x, d, len); +} + +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp) +{ +    int ret, j, bits, len; +    unsigned char *p, *d; + +    if (a == NULL) +        return (0); + +    len = a->length; + +    if (len > 0) { +        if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) { +            bits = (int)a->flags & 0x07; +        } else { +            for (; len > 0; len--) { +                if (a->data[len - 1]) +                    break; +            } +            j = a->data[len - 1]; +            if (j & 0x01) +                bits = 0; +            else if (j & 0x02) +                bits = 1; +            else if (j & 0x04) +                bits = 2; +            else if (j & 0x08) +                bits = 3; +            else if (j & 0x10) +                bits = 4; +            else if (j & 0x20) +                bits = 5; +            else if (j & 0x40) +                bits = 6; +            else if (j & 0x80) +                bits = 7; +            else +                bits = 0;       /* should not happen */ +        } +    } else +        bits = 0; + +    ret = 1 + len; +    if (pp == NULL) +        return (ret); + +    p = *pp; + +    *(p++) = (unsigned char)bits; +    d = a->data; +    if (len > 0) { +        memcpy(p, d, len); +        p += len; +        p[-1] &= (0xff << bits); +    } +    *pp = p; +    return (ret); +} + +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, +                                     const unsigned char **pp, long len) +{ +    ASN1_BIT_STRING *ret = NULL; +    const unsigned char *p; +    unsigned char *s; +    int i; + +    if (len < 1) { +        i = ASN1_R_STRING_TOO_SHORT; +        goto err; +    } + +    if (len > INT_MAX) { +        i = ASN1_R_STRING_TOO_LONG; +        goto err; +    } + +    if ((a == NULL) || ((*a) == NULL)) { +        if ((ret = ASN1_BIT_STRING_new()) == NULL) +            return (NULL); +    } else +        ret = (*a); + +    p = *pp; +    i = *(p++); +    if (i > 7) { +        i = ASN1_R_INVALID_BIT_STRING_BITS_LEFT; +        goto err; +    } +    /* +     * We do this to preserve the settings.  If we modify the settings, via +     * the _set_bit function, we will recalculate on output +     */ +    ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */ +    ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | i); /* set */ + +    if (len-- > 1) {            /* using one because of the bits left byte */ +        s = OPENSSL_malloc((int)len); +        if (s == NULL) { +            i = ERR_R_MALLOC_FAILURE; +            goto err; +        } +        memcpy(s, p, (int)len); +        s[len - 1] &= (0xff << i); +        p += len; +    } else +        s = NULL; + +    ret->length = (int)len; +    OPENSSL_free(ret->data); +    ret->data = s; +    ret->type = V_ASN1_BIT_STRING; +    if (a != NULL) +        (*a) = ret; +    *pp = p; +    return (ret); + err: +    ASN1err(ASN1_F_C2I_ASN1_BIT_STRING, i); +    if ((a == NULL) || (*a != ret)) +        ASN1_BIT_STRING_free(ret); +    return (NULL); +} + +/* + * These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de> + */ +int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value) +{ +    int w, v, iv; +    unsigned char *c; + +    w = n / 8; +    v = 1 << (7 - (n & 0x07)); +    iv = ~v; +    if (!value) +        v = 0; + +    if (a == NULL) +        return 0; + +    a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */ + +    if ((a->length < (w + 1)) || (a->data == NULL)) { +        if (!value) +            return (1);         /* Don't need to set */ +        c = OPENSSL_clear_realloc(a->data, a->length, w + 1); +        if (c == NULL) { +            ASN1err(ASN1_F_ASN1_BIT_STRING_SET_BIT, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        if (w + 1 - a->length > 0) +            memset(c + a->length, 0, w + 1 - a->length); +        a->data = c; +        a->length = w + 1; +    } +    a->data[w] = ((a->data[w]) & iv) | v; +    while ((a->length > 0) && (a->data[a->length - 1] == 0)) +        a->length--; +    return (1); +} + +int ASN1_BIT_STRING_get_bit(const ASN1_BIT_STRING *a, int n) +{ +    int w, v; + +    w = n / 8; +    v = 1 << (7 - (n & 0x07)); +    if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL)) +        return (0); +    return ((a->data[w] & v) != 0); +} + +/* + * Checks if the given bit string contains only bits specified by + * the flags vector. Returns 0 if there is at least one bit set in 'a' + * which is not specified in 'flags', 1 otherwise. + * 'len' is the length of 'flags'. + */ +int ASN1_BIT_STRING_check(const ASN1_BIT_STRING *a, +                          const unsigned char *flags, int flags_len) +{ +    int i, ok; +    /* Check if there is one bit set at all. */ +    if (!a || !a->data) +        return 1; + +    /* +     * Check each byte of the internal representation of the bit string. +     */ +    ok = 1; +    for (i = 0; i < a->length && ok; ++i) { +        unsigned char mask = i < flags_len ? ~flags[i] : 0xff; +        /* We are done if there is an unneeded bit set. */ +        ok = (a->data[i] & mask) == 0; +    } +    return ok; +} diff --git a/openssl-1.1.0h/crypto/asn1/a_d2i_fp.c b/openssl-1.1.0h/crypto/asn1/a_d2i_fp.c new file mode 100644 index 0000000..e5c1d0e --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_d2i_fp.c @@ -0,0 +1,235 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <limits.h> +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include <openssl/buffer.h> +#include <openssl/asn1.h> + +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb); + +#ifndef NO_OLD_ASN1 +# ifndef OPENSSL_NO_STDIO + +void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x) +{ +    BIO *b; +    void *ret; + +    if ((b = BIO_new(BIO_s_file())) == NULL) { +        ASN1err(ASN1_F_ASN1_D2I_FP, ERR_R_BUF_LIB); +        return (NULL); +    } +    BIO_set_fp(b, in, BIO_NOCLOSE); +    ret = ASN1_d2i_bio(xnew, d2i, b, x); +    BIO_free(b); +    return (ret); +} +# endif + +void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x) +{ +    BUF_MEM *b = NULL; +    const unsigned char *p; +    void *ret = NULL; +    int len; + +    len = asn1_d2i_read_bio(in, &b); +    if (len < 0) +        goto err; + +    p = (unsigned char *)b->data; +    ret = d2i(x, &p, len); + err: +    BUF_MEM_free(b); +    return (ret); +} + +#endif + +void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x) +{ +    BUF_MEM *b = NULL; +    const unsigned char *p; +    void *ret = NULL; +    int len; + +    len = asn1_d2i_read_bio(in, &b); +    if (len < 0) +        goto err; + +    p = (const unsigned char *)b->data; +    ret = ASN1_item_d2i(x, &p, len, it); + err: +    BUF_MEM_free(b); +    return (ret); +} + +#ifndef OPENSSL_NO_STDIO +void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x) +{ +    BIO *b; +    char *ret; + +    if ((b = BIO_new(BIO_s_file())) == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_D2I_FP, ERR_R_BUF_LIB); +        return (NULL); +    } +    BIO_set_fp(b, in, BIO_NOCLOSE); +    ret = ASN1_item_d2i_bio(it, b, x); +    BIO_free(b); +    return (ret); +} +#endif + +#define HEADER_SIZE   8 +#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024) +static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb) +{ +    BUF_MEM *b; +    unsigned char *p; +    int i; +    size_t want = HEADER_SIZE; +    uint32_t eos = 0; +    size_t off = 0; +    size_t len = 0; + +    const unsigned char *q; +    long slen; +    int inf, tag, xclass; + +    b = BUF_MEM_new(); +    if (b == NULL) { +        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); +        return -1; +    } + +    ERR_clear_error(); +    for (;;) { +        if (want >= (len - off)) { +            want -= (len - off); + +            if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) { +                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); +                goto err; +            } +            i = BIO_read(in, &(b->data[len]), want); +            if ((i < 0) && ((len - off) == 0)) { +                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA); +                goto err; +            } +            if (i > 0) { +                if (len + i < len) { +                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); +                    goto err; +                } +                len += i; +            } +        } +        /* else data already loaded */ + +        p = (unsigned char *)&(b->data[off]); +        q = p; +        inf = ASN1_get_object(&q, &slen, &tag, &xclass, len - off); +        if (inf & 0x80) { +            unsigned long e; + +            e = ERR_GET_REASON(ERR_peek_error()); +            if (e != ASN1_R_TOO_LONG) +                goto err; +            else +                ERR_clear_error(); /* clear error */ +        } +        i = q - p;            /* header length */ +        off += i;               /* end of data */ + +        if (inf & 1) { +            /* no data body so go round again */ +            if (eos == UINT32_MAX) { +                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_HEADER_TOO_LONG); +                goto err; +            } +            eos++; +            want = HEADER_SIZE; +        } else if (eos && (slen == 0) && (tag == V_ASN1_EOC)) { +            /* eos value, so go back and read another header */ +            eos--; +            if (eos == 0) +                break; +            else +                want = HEADER_SIZE; +        } else { +            /* suck in slen bytes of data */ +            want = slen; +            if (want > (len - off)) { +                size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE; + +                want -= (len - off); +                if (want > INT_MAX /* BIO_read takes an int length */  || +                    len + want < len) { +                    ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); +                    goto err; +                } +                while (want > 0) { +                    /* +                     * Read content in chunks of increasing size +                     * so we can return an error for EOF without +                     * having to allocate the entire content length +                     * in one go. +                     */ +                    size_t chunk = want > chunk_max ? chunk_max : want; + +                    if (!BUF_MEM_grow_clean(b, len + chunk)) { +                        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ERR_R_MALLOC_FAILURE); +                        goto err; +                    } +                    want -= chunk; +                    while (chunk > 0) { +                        i = BIO_read(in, &(b->data[len]), chunk); +                        if (i <= 0) { +                            ASN1err(ASN1_F_ASN1_D2I_READ_BIO, +                                    ASN1_R_NOT_ENOUGH_DATA); +                            goto err; +                        } +                    /* +                     * This can't overflow because |len+want| didn't +                     * overflow. +                     */ +                        len += i; +                        chunk -= i; +                    } +                    if (chunk_max < INT_MAX/2) +                        chunk_max *= 2; +                } +            } +            if (off + slen < off) { +                ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); +                goto err; +            } +            off += slen; +            if (eos == 0) { +                break; +            } else +                want = HEADER_SIZE; +        } +    } + +    if (off > INT_MAX) { +        ASN1err(ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_TOO_LONG); +        goto err; +    } + +    *pb = b; +    return off; + err: +    BUF_MEM_free(b); +    return -1; +} diff --git a/openssl-1.1.0h/crypto/asn1/a_digest.c b/openssl-1.1.0h/crypto/asn1/a_digest.c new file mode 100644 index 0000000..c84ecc9 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_digest.c @@ -0,0 +1,63 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> + +#include "internal/cryptlib.h" + +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/buffer.h> +#include <openssl/x509.h> + +#ifndef NO_ASN1_OLD + +int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data, +                unsigned char *md, unsigned int *len) +{ +    int i; +    unsigned char *str, *p; + +    i = i2d(data, NULL); +    if ((str = OPENSSL_malloc(i)) == NULL) { +        ASN1err(ASN1_F_ASN1_DIGEST, ERR_R_MALLOC_FAILURE); +        return (0); +    } +    p = str; +    i2d(data, &p); + +    if (!EVP_Digest(str, i, md, len, type, NULL)) { +        OPENSSL_free(str); +        return 0; +    } +    OPENSSL_free(str); +    return (1); +} + +#endif + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, +                     unsigned char *md, unsigned int *len) +{ +    int i; +    unsigned char *str = NULL; + +    i = ASN1_item_i2d(asn, &str, it); +    if (!str) +        return (0); + +    if (!EVP_Digest(str, i, md, len, type, NULL)) { +        OPENSSL_free(str); +        return 0; +    } +    OPENSSL_free(str); +    return (1); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_dup.c b/openssl-1.1.0h/crypto/asn1/a_dup.c new file mode 100644 index 0000000..d9a57b2 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_dup.c @@ -0,0 +1,68 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +#ifndef NO_OLD_ASN1 + +void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x) +{ +    unsigned char *b, *p; +    const unsigned char *p2; +    int i; +    char *ret; + +    if (x == NULL) +        return (NULL); + +    i = i2d(x, NULL); +    b = OPENSSL_malloc(i + 10); +    if (b == NULL) { +        ASN1err(ASN1_F_ASN1_DUP, ERR_R_MALLOC_FAILURE); +        return (NULL); +    } +    p = b; +    i = i2d(x, &p); +    p2 = b; +    ret = d2i(NULL, &p2, i); +    OPENSSL_free(b); +    return (ret); +} + +#endif + +/* + * ASN1_ITEM version of dup: this follows the model above except we don't + * need to allocate the buffer. At some point this could be rewritten to + * directly dup the underlying structure instead of doing and encode and + * decode. + */ + +void *ASN1_item_dup(const ASN1_ITEM *it, void *x) +{ +    unsigned char *b = NULL; +    const unsigned char *p; +    long i; +    void *ret; + +    if (x == NULL) +        return (NULL); + +    i = ASN1_item_i2d(x, &b, it); +    if (b == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_DUP, ERR_R_MALLOC_FAILURE); +        return (NULL); +    } +    p = b; +    ret = ASN1_item_d2i(NULL, &p, i, it); +    OPENSSL_free(b); +    return (ret); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_gentm.c b/openssl-1.1.0h/crypto/asn1/a_gentm.c new file mode 100644 index 0000000..ff1b695 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_gentm.c @@ -0,0 +1,273 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * GENERALIZEDTIME implementation. Based on UTCTIME + */ + +#include <stdio.h> +#include <time.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include "asn1_locl.h" + +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d) +{ +    static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 }; +    static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 }; +    char *a; +    int n, i, l, o; + +    if (d->type != V_ASN1_GENERALIZEDTIME) +        return (0); +    l = d->length; +    a = (char *)d->data; +    o = 0; +    /* +     * GENERALIZEDTIME is similar to UTCTIME except the year is represented +     * as YYYY. This stuff treats everything as a two digit field so make +     * first two fields 00 to 99 +     */ +    if (l < 13) +        goto err; +    for (i = 0; i < 7; i++) { +        if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { +            i++; +            if (tm) +                tm->tm_sec = 0; +            break; +        } +        if ((a[o] < '0') || (a[o] > '9')) +            goto err; +        n = a[o] - '0'; +        if (++o > l) +            goto err; + +        if ((a[o] < '0') || (a[o] > '9')) +            goto err; +        n = (n * 10) + a[o] - '0'; +        if (++o > l) +            goto err; + +        if ((n < min[i]) || (n > max[i])) +            goto err; +        if (tm) { +            switch (i) { +            case 0: +                tm->tm_year = n * 100 - 1900; +                break; +            case 1: +                tm->tm_year += n; +                break; +            case 2: +                tm->tm_mon = n - 1; +                break; +            case 3: +                tm->tm_mday = n; +                break; +            case 4: +                tm->tm_hour = n; +                break; +            case 5: +                tm->tm_min = n; +                break; +            case 6: +                tm->tm_sec = n; +                break; +            } +        } +    } +    /* +     * Optional fractional seconds: decimal point followed by one or more +     * digits. +     */ +    if (a[o] == '.') { +        if (++o > l) +            goto err; +        i = o; +        while ((a[o] >= '0') && (a[o] <= '9') && (o <= l)) +            o++; +        /* Must have at least one digit after decimal point */ +        if (i == o) +            goto err; +    } + +    if (a[o] == 'Z') +        o++; +    else if ((a[o] == '+') || (a[o] == '-')) { +        int offsign = a[o] == '-' ? 1 : -1, offset = 0; +        o++; +        if (o + 4 > l) +            goto err; +        for (i = 7; i < 9; i++) { +            if ((a[o] < '0') || (a[o] > '9')) +                goto err; +            n = a[o] - '0'; +            o++; +            if ((a[o] < '0') || (a[o] > '9')) +                goto err; +            n = (n * 10) + a[o] - '0'; +            if ((n < min[i]) || (n > max[i])) +                goto err; +            if (tm) { +                if (i == 7) +                    offset = n * 3600; +                else if (i == 8) +                    offset += n * 60; +            } +            o++; +        } +        if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) +            return 0; +    } else if (a[o]) { +        /* Missing time zone information. */ +        goto err; +    } +    return (o == l); + err: +    return (0); +} + +int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d) +{ +    return asn1_generalizedtime_to_tm(NULL, d); +} + +int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str) +{ +    ASN1_GENERALIZEDTIME t; + +    t.type = V_ASN1_GENERALIZEDTIME; +    t.length = strlen(str); +    t.data = (unsigned char *)str; +    if (ASN1_GENERALIZEDTIME_check(&t)) { +        if (s != NULL) { +            if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length)) +                return 0; +            s->type = V_ASN1_GENERALIZEDTIME; +        } +        return (1); +    } else +        return (0); +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s, +                                               time_t t) +{ +    return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0); +} + +ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s, +                                               time_t t, int offset_day, +                                               long offset_sec) +{ +    char *p; +    struct tm *ts; +    struct tm data; +    size_t len = 20; +    ASN1_GENERALIZEDTIME *tmps = NULL; + +    if (s == NULL) +        tmps = ASN1_GENERALIZEDTIME_new(); +    else +        tmps = s; +    if (tmps == NULL) +        return NULL; + +    ts = OPENSSL_gmtime(&t, &data); +    if (ts == NULL) +        goto err; + +    if (offset_day || offset_sec) { +        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) +            goto err; +    } + +    p = (char *)tmps->data; +    if ((p == NULL) || ((size_t)tmps->length < len)) { +        p = OPENSSL_malloc(len); +        if (p == NULL) { +            ASN1err(ASN1_F_ASN1_GENERALIZEDTIME_ADJ, ERR_R_MALLOC_FAILURE); +            goto err; +        } +        OPENSSL_free(tmps->data); +        tmps->data = (unsigned char *)p; +    } + +    BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900, +                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, +                 ts->tm_sec); +    tmps->length = strlen(p); +    tmps->type = V_ASN1_GENERALIZEDTIME; +#ifdef CHARSET_EBCDIC_not +    ebcdic2ascii(tmps->data, tmps->data, tmps->length); +#endif +    return tmps; + err: +    if (s == NULL) +        ASN1_GENERALIZEDTIME_free(tmps); +    return NULL; +} + +const char *_asn1_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", +                   _asn1_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); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_i2d_fp.c b/openssl-1.1.0h/crypto/asn1/a_i2d_fp.c new file mode 100644 index 0000000..3b3f713 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_i2d_fp.c @@ -0,0 +1,111 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/asn1.h> + +#ifndef NO_OLD_ASN1 + +# ifndef OPENSSL_NO_STDIO +int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x) +{ +    BIO *b; +    int ret; + +    if ((b = BIO_new(BIO_s_file())) == NULL) { +        ASN1err(ASN1_F_ASN1_I2D_FP, ERR_R_BUF_LIB); +        return (0); +    } +    BIO_set_fp(b, out, BIO_NOCLOSE); +    ret = ASN1_i2d_bio(i2d, b, x); +    BIO_free(b); +    return (ret); +} +# endif + +int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, unsigned char *x) +{ +    char *b; +    unsigned char *p; +    int i, j = 0, n, ret = 1; + +    n = i2d(x, NULL); +    if (n <= 0) +        return 0; + +    b = OPENSSL_malloc(n); +    if (b == NULL) { +        ASN1err(ASN1_F_ASN1_I2D_BIO, ERR_R_MALLOC_FAILURE); +        return (0); +    } + +    p = (unsigned char *)b; +    i2d(x, &p); + +    for (;;) { +        i = BIO_write(out, &(b[j]), n); +        if (i == n) +            break; +        if (i <= 0) { +            ret = 0; +            break; +        } +        j += i; +        n -= i; +    } +    OPENSSL_free(b); +    return (ret); +} + +#endif + +#ifndef OPENSSL_NO_STDIO +int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x) +{ +    BIO *b; +    int ret; + +    if ((b = BIO_new(BIO_s_file())) == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_I2D_FP, ERR_R_BUF_LIB); +        return (0); +    } +    BIO_set_fp(b, out, BIO_NOCLOSE); +    ret = ASN1_item_i2d_bio(it, b, x); +    BIO_free(b); +    return (ret); +} +#endif + +int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x) +{ +    unsigned char *b = NULL; +    int i, j = 0, n, ret = 1; + +    n = ASN1_item_i2d(x, &b, it); +    if (b == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_I2D_BIO, ERR_R_MALLOC_FAILURE); +        return (0); +    } + +    for (;;) { +        i = BIO_write(out, &(b[j]), n); +        if (i == n) +            break; +        if (i <= 0) { +            ret = 0; +            break; +        } +        j += i; +        n -= i; +    } +    OPENSSL_free(b); +    return (ret); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_int.c b/openssl-1.1.0h/crypto/asn1/a_int.c new file mode 100644 index 0000000..217650a --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_int.c @@ -0,0 +1,630 @@ +/* + * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include "internal/numbers.h" +#include <limits.h> +#include <openssl/asn1.h> +#include <openssl/bn.h> +#include "asn1_locl.h" + +ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x) +{ +    return ASN1_STRING_dup(x); +} + +int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y) +{ +    int neg, ret; +    /* Compare signs */ +    neg = x->type & V_ASN1_NEG; +    if (neg != (y->type & V_ASN1_NEG)) { +        if (neg) +            return -1; +        else +            return 1; +    } + +    ret = ASN1_STRING_cmp(x, y); + +    if (neg) +        return -ret; +    else +        return ret; +} + +/*- + * This converts a big endian buffer and sign into its content encoding. + * This is used for INTEGER and ENUMERATED types. + * The internal representation is an ASN1_STRING whose data is a big endian + * representation of the value, ignoring the sign. The sign is determined by + * the type: if type & V_ASN1_NEG is true it is negative, otherwise positive. + * + * Positive integers are no problem: they are almost the same as the DER + * encoding, except if the first byte is >= 0x80 we need to add a zero pad. + * + * Negative integers are a bit trickier... + * The DER representation of negative integers is in 2s complement form. + * The internal form is converted by complementing each octet and finally + * adding one to the result. This can be done less messily with a little trick. + * If the internal form has trailing zeroes then they will become FF by the + * complement and 0 by the add one (due to carry) so just copy as many trailing + * zeros to the destination as there are in the source. The carry will add one + * to the last none zero octet: so complement this octet and add one and finally + * complement any left over until you get to the start of the string. + * + * Padding is a little trickier too. If the first bytes is > 0x80 then we pad + * with 0xff. However if the first byte is 0x80 and one of the following bytes + * is non-zero we pad with 0xff. The reason for this distinction is that 0x80 + * followed by optional zeros isn't padded. + */ + +/* + * If |pad| is zero, the operation is effectively reduced to memcpy, + * and if |pad| is 0xff, then it performs two's complement, ~dst + 1. + * Note that in latter case sequence of zeros yields itself, and so + * does 0x80 followed by any number of zeros. These properties are + * used elsewhere below... + */ +static void twos_complement(unsigned char *dst, const unsigned char *src, +                            size_t len, unsigned char pad) +{ +    unsigned int carry = pad & 1; + +    /* Begin at the end of the encoding */ +    dst += len; +    src += len; +    /* two's complement value: ~value + 1 */ +    while (len-- != 0) { +        *(--dst) = (unsigned char)(carry += *(--src) ^ pad); +        carry >>= 8; +    } +} + +static size_t i2c_ibuf(const unsigned char *b, size_t blen, int neg, +                       unsigned char **pp) +{ +    unsigned int pad = 0; +    size_t ret, i; +    unsigned char *p, pb = 0; + +    if (b != NULL && blen) { +        ret = blen; +        i = b[0]; +        if (!neg && (i > 127)) { +            pad = 1; +            pb = 0; +        } else if (neg) { +            pb = 0xFF; +            if (i > 128) { +                pad = 1; +            } else if (i == 128) { +                /* +                 * Special case [of minimal negative for given length]: +                 * if any other bytes non zero we pad, otherwise we don't. +                 */ +                for (pad = 0, i = 1; i < blen; i++) +                    pad |= b[i]; +                pb = pad != 0 ? 0xffU : 0; +                pad = pb & 1; +            } +        } +        ret += pad; +    } else { +        ret = 1; +        blen = 0;   /* reduce '(b == NULL || blen == 0)' to '(blen == 0)' */ +    } + +    if (pp == NULL || (p = *pp) == NULL) +        return ret; + +    /* +     * This magically handles all corner cases, such as '(b == NULL || +     * blen == 0)', non-negative value, "negative" zero, 0x80 followed +     * by any number of zeros... +     */ +    *p = pb; +    p += pad;       /* yes, p[0] can be written twice, but it's little +                     * price to pay for eliminated branches */ +    twos_complement(p, b, blen, pb); + +    *pp += ret; +    return ret; +} + +/* + * convert content octets into a big endian buffer. Returns the length + * of buffer or 0 on error: for malformed INTEGER. If output buffer is + * NULL just return length. + */ + +static size_t c2i_ibuf(unsigned char *b, int *pneg, +                       const unsigned char *p, size_t plen) +{ +    int neg, pad; +    /* Zero content length is illegal */ +    if (plen == 0) { +        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_ZERO_CONTENT); +        return 0; +    } +    neg = p[0] & 0x80; +    if (pneg) +        *pneg = neg; +    /* Handle common case where length is 1 octet separately */ +    if (plen == 1) { +        if (b != NULL) { +            if (neg) +                b[0] = (p[0] ^ 0xFF) + 1; +            else +                b[0] = p[0]; +        } +        return 1; +    } + +    pad = 0; +    if (p[0] == 0) { +        pad = 1; +    } else if (p[0] == 0xFF) { +        size_t i; + +        /* +         * Special case [of "one less minimal negative" for given length]: +         * if any other bytes non zero it was padded, otherwise not. +         */ +        for (pad = 0, i = 1; i < plen; i++) +            pad |= p[i]; +        pad = pad != 0 ? 1 : 0; +    } +    /* reject illegal padding: first two octets MSB can't match */ +    if (pad && (neg == (p[1] & 0x80))) { +        ASN1err(ASN1_F_C2I_IBUF, ASN1_R_ILLEGAL_PADDING); +        return 0; +    } + +    /* skip over pad */ +    p += pad; +    plen -= pad; + +    if (b != NULL) +        twos_complement(b, p, plen, neg ? 0xffU : 0); + +    return plen; +} + +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp) +{ +    return i2c_ibuf(a->data, a->length, a->type & V_ASN1_NEG, pp); +} + +/* Convert big endian buffer into uint64_t, return 0 on error */ +static int asn1_get_uint64(uint64_t *pr, const unsigned char *b, size_t blen) +{ +    size_t i; +    uint64_t r; + +    if (blen > sizeof(*pr)) { +        ASN1err(ASN1_F_ASN1_GET_UINT64, ASN1_R_TOO_LARGE); +        return 0; +    } +    if (b == NULL) +        return 0; +    for (r = 0, i = 0; i < blen; i++) { +        r <<= 8; +        r |= b[i]; +    } +    *pr = r; +    return 1; +} + +/* + * Write uint64_t to big endian buffer and return offset to first + * written octet. In other words it returns offset in range from 0 + * to 7, with 0 denoting 8 written octets and 7 - one. + */ +static size_t asn1_put_uint64(unsigned char b[sizeof(uint64_t)], uint64_t r) +{ +    size_t off = sizeof(uint64_t); + +    do { +        b[--off] = (unsigned char)r; +    } while (r >>= 8); + +    return off; +} + +/* + * Absolute value of INT64_MIN: we can't just use -INT64_MIN as gcc produces + * overflow warnings. + */ +#define ABS_INT64_MIN ((uint64_t)INT64_MAX + (-(INT64_MIN + INT64_MAX))) + +/* signed version of asn1_get_uint64 */ +static int asn1_get_int64(int64_t *pr, const unsigned char *b, size_t blen, +                          int neg) +{ +    uint64_t r; +    if (asn1_get_uint64(&r, b, blen) == 0) +        return 0; +    if (neg) { +        if (r <= INT64_MAX) { +            /* Most significant bit is guaranteed to be clear, negation +             * is guaranteed to be meaningful in platform-neutral sense. */ +            *pr = -(int64_t)r; +        } else if (r == ABS_INT64_MIN) { +            /* This never happens if INT64_MAX == ABS_INT64_MIN, e.g. +             * on ones'-complement system. */ +            *pr = (int64_t)(0 - r); +        } else { +            ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_SMALL); +            return 0; +        } +    } else { +        if (r <= INT64_MAX) { +            *pr = (int64_t)r; +        } else { +            ASN1err(ASN1_F_ASN1_GET_INT64, ASN1_R_TOO_LARGE); +            return 0; +        } +    } +    return 1; +} + +/* Convert ASN1 INTEGER content octets to ASN1_INTEGER structure */ +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, +                               long len) +{ +    ASN1_INTEGER *ret = NULL; +    size_t r; +    int neg; + +    r = c2i_ibuf(NULL, NULL, *pp, len); + +    if (r == 0) +        return NULL; + +    if ((a == NULL) || ((*a) == NULL)) { +        ret = ASN1_INTEGER_new(); +        if (ret == NULL) +            return NULL; +        ret->type = V_ASN1_INTEGER; +    } else +        ret = *a; + +    if (ASN1_STRING_set(ret, NULL, r) == 0) +        goto err; + +    c2i_ibuf(ret->data, &neg, *pp, len); + +    if (neg) +        ret->type |= V_ASN1_NEG; + +    *pp += len; +    if (a != NULL) +        (*a) = ret; +    return ret; + err: +    ASN1err(ASN1_F_C2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); +    if ((a == NULL) || (*a != ret)) +        ASN1_INTEGER_free(ret); +    return NULL; +} + +static int asn1_string_get_int64(int64_t *pr, const ASN1_STRING *a, int itype) +{ +    if (a == NULL) { +        ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ERR_R_PASSED_NULL_PARAMETER); +        return 0; +    } +    if ((a->type & ~V_ASN1_NEG) != itype) { +        ASN1err(ASN1_F_ASN1_STRING_GET_INT64, ASN1_R_WRONG_INTEGER_TYPE); +        return 0; +    } +    return asn1_get_int64(pr, a->data, a->length, a->type & V_ASN1_NEG); +} + +static int asn1_string_set_int64(ASN1_STRING *a, int64_t r, int itype) +{ +    unsigned char tbuf[sizeof(r)]; +    size_t off; + +    a->type = itype; +    if (r < 0) { +        /* Most obvious '-r' triggers undefined behaviour for most +         * common INT64_MIN. Even though below '0 - (uint64_t)r' can +         * appear two's-complement centric, it does produce correct/ +         * expected result even on one's-complement. This is because +         * cast to unsigned has to change bit pattern... */ +        off = asn1_put_uint64(tbuf, 0 - (uint64_t)r); +        a->type |= V_ASN1_NEG; +    } else { +        off = asn1_put_uint64(tbuf, r); +        a->type &= ~V_ASN1_NEG; +    } +    return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off); +} + +static int asn1_string_get_uint64(uint64_t *pr, const ASN1_STRING *a, +                                  int itype) +{ +    if (a == NULL) { +        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ERR_R_PASSED_NULL_PARAMETER); +        return 0; +    } +    if ((a->type & ~V_ASN1_NEG) != itype) { +        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_WRONG_INTEGER_TYPE); +        return 0; +    } +    if (a->type & V_ASN1_NEG) { +        ASN1err(ASN1_F_ASN1_STRING_GET_UINT64, ASN1_R_ILLEGAL_NEGATIVE_VALUE); +        return 0; +    } +    return asn1_get_uint64(pr, a->data, a->length); +} + +static int asn1_string_set_uint64(ASN1_STRING *a, uint64_t r, int itype) +{ +    unsigned char tbuf[sizeof(r)]; +    size_t off; + +    a->type = itype; +    off = asn1_put_uint64(tbuf, r); +    return ASN1_STRING_set(a, tbuf + off, sizeof(tbuf) - off); +} + +/* + * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1 + * integers: some broken software can encode a positive INTEGER with its MSB + * set as negative (it doesn't add a padding zero). + */ + +ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp, +                                long length) +{ +    ASN1_INTEGER *ret = NULL; +    const unsigned char *p; +    unsigned char *s; +    long len; +    int inf, tag, xclass; +    int i; + +    if ((a == NULL) || ((*a) == NULL)) { +        if ((ret = ASN1_INTEGER_new()) == NULL) +            return (NULL); +        ret->type = V_ASN1_INTEGER; +    } else +        ret = (*a); + +    p = *pp; +    inf = ASN1_get_object(&p, &len, &tag, &xclass, length); +    if (inf & 0x80) { +        i = ASN1_R_BAD_OBJECT_HEADER; +        goto err; +    } + +    if (tag != V_ASN1_INTEGER) { +        i = ASN1_R_EXPECTING_AN_INTEGER; +        goto err; +    } + +    /* +     * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies +     * a missing NULL parameter. +     */ +    s = OPENSSL_malloc((int)len + 1); +    if (s == NULL) { +        i = ERR_R_MALLOC_FAILURE; +        goto err; +    } +    ret->type = V_ASN1_INTEGER; +    if (len) { +        if ((*p == 0) && (len != 1)) { +            p++; +            len--; +        } +        memcpy(s, p, (int)len); +        p += len; +    } + +    OPENSSL_free(ret->data); +    ret->data = s; +    ret->length = (int)len; +    if (a != NULL) +        (*a) = ret; +    *pp = p; +    return (ret); + err: +    ASN1err(ASN1_F_D2I_ASN1_UINTEGER, i); +    if ((a == NULL) || (*a != ret)) +        ASN1_INTEGER_free(ret); +    return (NULL); +} + +static ASN1_STRING *bn_to_asn1_string(const BIGNUM *bn, ASN1_STRING *ai, +                                      int atype) +{ +    ASN1_INTEGER *ret; +    int len; + +    if (ai == NULL) { +        ret = ASN1_STRING_type_new(atype); +    } else { +        ret = ai; +        ret->type = atype; +    } + +    if (ret == NULL) { +        ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_NESTED_ASN1_ERROR); +        goto err; +    } + +    if (BN_is_negative(bn) && !BN_is_zero(bn)) +        ret->type |= V_ASN1_NEG_INTEGER; + +    len = BN_num_bytes(bn); + +    if (len == 0) +        len = 1; + +    if (ASN1_STRING_set(ret, NULL, len) == 0) { +        ASN1err(ASN1_F_BN_TO_ASN1_STRING, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    /* Correct zero case */ +    if (BN_is_zero(bn)) +        ret->data[0] = 0; +    else +        len = BN_bn2bin(bn, ret->data); +    ret->length = len; +    return ret; + err: +    if (ret != ai) +        ASN1_INTEGER_free(ret); +    return (NULL); +} + +static BIGNUM *asn1_string_to_bn(const ASN1_INTEGER *ai, BIGNUM *bn, +                                 int itype) +{ +    BIGNUM *ret; + +    if ((ai->type & ~V_ASN1_NEG) != itype) { +        ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_WRONG_INTEGER_TYPE); +        return NULL; +    } + +    ret = BN_bin2bn(ai->data, ai->length, bn); +    if (ret == NULL) { +        ASN1err(ASN1_F_ASN1_STRING_TO_BN, ASN1_R_BN_LIB); +        return NULL; +    } +    if (ai->type & V_ASN1_NEG) +        BN_set_negative(ret, 1); +    return ret; +} + +int ASN1_INTEGER_get_int64(int64_t *pr, const ASN1_INTEGER *a) +{ +    return asn1_string_get_int64(pr, a, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set_int64(ASN1_INTEGER *a, int64_t r) +{ +    return asn1_string_set_int64(a, r, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_get_uint64(uint64_t *pr, const ASN1_INTEGER *a) +{ +    return asn1_string_get_uint64(pr, a, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set_uint64(ASN1_INTEGER *a, uint64_t r) +{ +    return asn1_string_set_uint64(a, r, V_ASN1_INTEGER); +} + +int ASN1_INTEGER_set(ASN1_INTEGER *a, long v) +{ +    return ASN1_INTEGER_set_int64(a, v); +} + +long ASN1_INTEGER_get(const ASN1_INTEGER *a) +{ +    int i; +    int64_t r; +    if (a == NULL) +        return 0; +    i = ASN1_INTEGER_get_int64(&r, a); +    if (i == 0) +        return -1; +    if (r > LONG_MAX || r < LONG_MIN) +        return -1; +    return (long)r; +} + +ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai) +{ +    return bn_to_asn1_string(bn, ai, V_ASN1_INTEGER); +} + +BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn) +{ +    return asn1_string_to_bn(ai, bn, V_ASN1_INTEGER); +} + +int ASN1_ENUMERATED_get_int64(int64_t *pr, const ASN1_ENUMERATED *a) +{ +    return asn1_string_get_int64(pr, a, V_ASN1_ENUMERATED); +} + +int ASN1_ENUMERATED_set_int64(ASN1_ENUMERATED *a, int64_t r) +{ +    return asn1_string_set_int64(a, r, V_ASN1_ENUMERATED); +} + +int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v) +{ +    return ASN1_ENUMERATED_set_int64(a, v); +} + +long ASN1_ENUMERATED_get(const ASN1_ENUMERATED *a) +{ +    int i; +    int64_t r; +    if (a == NULL) +        return 0; +    if ((a->type & ~V_ASN1_NEG) != V_ASN1_ENUMERATED) +        return -1; +    if (a->length > (int)sizeof(long)) +        return 0xffffffffL; +    i = ASN1_ENUMERATED_get_int64(&r, a); +    if (i == 0) +        return -1; +    if (r > LONG_MAX || r < LONG_MIN) +        return -1; +    return (long)r; +} + +ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(const BIGNUM *bn, ASN1_ENUMERATED *ai) +{ +    return bn_to_asn1_string(bn, ai, V_ASN1_ENUMERATED); +} + +BIGNUM *ASN1_ENUMERATED_to_BN(const ASN1_ENUMERATED *ai, BIGNUM *bn) +{ +    return asn1_string_to_bn(ai, bn, V_ASN1_ENUMERATED); +} + +/* Internal functions used by x_int64.c */ +int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len) +{ +    unsigned char buf[sizeof(uint64_t)]; +    size_t buflen; + +    buflen = c2i_ibuf(NULL, NULL, *pp, len); +    if (buflen == 0) +        return 0; +    if (buflen > sizeof(uint64_t)) { +        ASN1err(ASN1_F_C2I_UINT64_INT, ASN1_R_TOO_LARGE); +        return 0; +    } +    (void)c2i_ibuf(buf, neg, *pp, len); +    return asn1_get_uint64(ret, buf, buflen); +} + +int i2c_uint64_int(unsigned char *p, uint64_t r, int neg) +{ +    unsigned char buf[sizeof(uint64_t)]; +    size_t off; + +    off = asn1_put_uint64(buf, r); +    return i2c_ibuf(buf + off, sizeof(buf) - off, neg, &p); +} + diff --git a/openssl-1.1.0h/crypto/asn1/a_mbstr.c b/openssl-1.1.0h/crypto/asn1/a_mbstr.c new file mode 100644 index 0000000..7a035af --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_mbstr.c @@ -0,0 +1,395 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +static int traverse_string(const unsigned char *p, int len, int inform, +                           int (*rfunc) (unsigned long value, void *in), +                           void *arg); +static int in_utf8(unsigned long value, void *arg); +static int out_utf8(unsigned long value, void *arg); +static int type_str(unsigned long value, void *arg); +static int cpy_asc(unsigned long value, void *arg); +static int cpy_bmp(unsigned long value, void *arg); +static int cpy_univ(unsigned long value, void *arg); +static int cpy_utf8(unsigned long value, void *arg); +static int is_numeric(unsigned long value); +static int is_printable(unsigned long value); + +/* + * These functions take a string in UTF8, ASCII or multibyte form and a mask + * of permissible ASN1 string types. It then works out the minimal type + * (using the order Numeric < Printable < IA5 < T61 < BMP < Universal < UTF8) + * and creates a string of the correct type with the supplied data. Yes this is + * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum + * size limits too. + */ + +int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len, +                       int inform, unsigned long mask) +{ +    return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0); +} + +int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len, +                        int inform, unsigned long mask, +                        long minsize, long maxsize) +{ +    int str_type; +    int ret; +    char free_out; +    int outform, outlen = 0; +    ASN1_STRING *dest; +    unsigned char *p; +    int nchar; +    char strbuf[32]; +    int (*cpyfunc) (unsigned long, void *) = NULL; +    if (len == -1) +        len = strlen((const char *)in); +    if (!mask) +        mask = DIRSTRING_TYPE; + +    /* First do a string check and work out the number of characters */ +    switch (inform) { + +    case MBSTRING_BMP: +        if (len & 1) { +            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, +                    ASN1_R_INVALID_BMPSTRING_LENGTH); +            return -1; +        } +        nchar = len >> 1; +        break; + +    case MBSTRING_UNIV: +        if (len & 3) { +            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, +                    ASN1_R_INVALID_UNIVERSALSTRING_LENGTH); +            return -1; +        } +        nchar = len >> 2; +        break; + +    case MBSTRING_UTF8: +        nchar = 0; +        /* This counts the characters and does utf8 syntax checking */ +        ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar); +        if (ret < 0) { +            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_INVALID_UTF8STRING); +            return -1; +        } +        break; + +    case MBSTRING_ASC: +        nchar = len; +        break; + +    default: +        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_UNKNOWN_FORMAT); +        return -1; +    } + +    if ((minsize > 0) && (nchar < minsize)) { +        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_SHORT); +        BIO_snprintf(strbuf, sizeof(strbuf), "%ld", minsize); +        ERR_add_error_data(2, "minsize=", strbuf); +        return -1; +    } + +    if ((maxsize > 0) && (nchar > maxsize)) { +        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_STRING_TOO_LONG); +        BIO_snprintf(strbuf, sizeof(strbuf), "%ld", maxsize); +        ERR_add_error_data(2, "maxsize=", strbuf); +        return -1; +    } + +    /* Now work out minimal type (if any) */ +    if (traverse_string(in, len, inform, type_str, &mask) < 0) { +        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ASN1_R_ILLEGAL_CHARACTERS); +        return -1; +    } + +    /* Now work out output format and string type */ +    outform = MBSTRING_ASC; +    if (mask & B_ASN1_NUMERICSTRING) +        str_type = V_ASN1_NUMERICSTRING; +    else if (mask & B_ASN1_PRINTABLESTRING) +        str_type = V_ASN1_PRINTABLESTRING; +    else if (mask & B_ASN1_IA5STRING) +        str_type = V_ASN1_IA5STRING; +    else if (mask & B_ASN1_T61STRING) +        str_type = V_ASN1_T61STRING; +    else if (mask & B_ASN1_BMPSTRING) { +        str_type = V_ASN1_BMPSTRING; +        outform = MBSTRING_BMP; +    } else if (mask & B_ASN1_UNIVERSALSTRING) { +        str_type = V_ASN1_UNIVERSALSTRING; +        outform = MBSTRING_UNIV; +    } else { +        str_type = V_ASN1_UTF8STRING; +        outform = MBSTRING_UTF8; +    } +    if (!out) +        return str_type; +    if (*out) { +        free_out = 0; +        dest = *out; +        OPENSSL_free(dest->data); +        dest->data = NULL; +        dest->length = 0; +        dest->type = str_type; +    } else { +        free_out = 1; +        dest = ASN1_STRING_type_new(str_type); +        if (dest == NULL) { +            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); +            return -1; +        } +        *out = dest; +    } +    /* If both the same type just copy across */ +    if (inform == outform) { +        if (!ASN1_STRING_set(dest, in, len)) { +            ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); +            return -1; +        } +        return str_type; +    } + +    /* Work out how much space the destination will need */ +    switch (outform) { +    case MBSTRING_ASC: +        outlen = nchar; +        cpyfunc = cpy_asc; +        break; + +    case MBSTRING_BMP: +        outlen = nchar << 1; +        cpyfunc = cpy_bmp; +        break; + +    case MBSTRING_UNIV: +        outlen = nchar << 2; +        cpyfunc = cpy_univ; +        break; + +    case MBSTRING_UTF8: +        outlen = 0; +        traverse_string(in, len, inform, out_utf8, &outlen); +        cpyfunc = cpy_utf8; +        break; +    } +    if ((p = OPENSSL_malloc(outlen + 1)) == NULL) { +        if (free_out) +            ASN1_STRING_free(dest); +        ASN1err(ASN1_F_ASN1_MBSTRING_NCOPY, ERR_R_MALLOC_FAILURE); +        return -1; +    } +    dest->length = outlen; +    dest->data = p; +    p[outlen] = 0; +    traverse_string(in, len, inform, cpyfunc, &p); +    return str_type; +} + +/* + * This function traverses a string and passes the value of each character to + * an optional function along with a void * argument. + */ + +static int traverse_string(const unsigned char *p, int len, int inform, +                           int (*rfunc) (unsigned long value, void *in), +                           void *arg) +{ +    unsigned long value; +    int ret; +    while (len) { +        if (inform == MBSTRING_ASC) { +            value = *p++; +            len--; +        } else if (inform == MBSTRING_BMP) { +            value = *p++ << 8; +            value |= *p++; +            len -= 2; +        } else if (inform == MBSTRING_UNIV) { +            value = ((unsigned long)*p++) << 24; +            value |= ((unsigned long)*p++) << 16; +            value |= *p++ << 8; +            value |= *p++; +            len -= 4; +        } else { +            ret = UTF8_getc(p, len, &value); +            if (ret < 0) +                return -1; +            len -= ret; +            p += ret; +        } +        if (rfunc) { +            ret = rfunc(value, arg); +            if (ret <= 0) +                return ret; +        } +    } +    return 1; +} + +/* Various utility functions for traverse_string */ + +/* Just count number of characters */ + +static int in_utf8(unsigned long value, void *arg) +{ +    int *nchar; +    nchar = arg; +    (*nchar)++; +    return 1; +} + +/* Determine size of output as a UTF8 String */ + +static int out_utf8(unsigned long value, void *arg) +{ +    int *outlen; +    outlen = arg; +    *outlen += UTF8_putc(NULL, -1, value); +    return 1; +} + +/* + * Determine the "type" of a string: check each character against a supplied + * "mask". + */ + +static int type_str(unsigned long value, void *arg) +{ +    unsigned long types; +    types = *((unsigned long *)arg); +    if ((types & B_ASN1_NUMERICSTRING) && !is_numeric(value)) +        types &= ~B_ASN1_NUMERICSTRING; +    if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value)) +        types &= ~B_ASN1_PRINTABLESTRING; +    if ((types & B_ASN1_IA5STRING) && (value > 127)) +        types &= ~B_ASN1_IA5STRING; +    if ((types & B_ASN1_T61STRING) && (value > 0xff)) +        types &= ~B_ASN1_T61STRING; +    if ((types & B_ASN1_BMPSTRING) && (value > 0xffff)) +        types &= ~B_ASN1_BMPSTRING; +    if (!types) +        return -1; +    *((unsigned long *)arg) = types; +    return 1; +} + +/* Copy one byte per character ASCII like strings */ + +static int cpy_asc(unsigned long value, void *arg) +{ +    unsigned char **p, *q; +    p = arg; +    q = *p; +    *q = (unsigned char)value; +    (*p)++; +    return 1; +} + +/* Copy two byte per character BMPStrings */ + +static int cpy_bmp(unsigned long value, void *arg) +{ +    unsigned char **p, *q; +    p = arg; +    q = *p; +    *q++ = (unsigned char)((value >> 8) & 0xff); +    *q = (unsigned char)(value & 0xff); +    *p += 2; +    return 1; +} + +/* Copy four byte per character UniversalStrings */ + +static int cpy_univ(unsigned long value, void *arg) +{ +    unsigned char **p, *q; +    p = arg; +    q = *p; +    *q++ = (unsigned char)((value >> 24) & 0xff); +    *q++ = (unsigned char)((value >> 16) & 0xff); +    *q++ = (unsigned char)((value >> 8) & 0xff); +    *q = (unsigned char)(value & 0xff); +    *p += 4; +    return 1; +} + +/* Copy to a UTF8String */ + +static int cpy_utf8(unsigned long value, void *arg) +{ +    unsigned char **p; +    int ret; +    p = arg; +    /* We already know there is enough room so pass 0xff as the length */ +    ret = UTF8_putc(*p, 0xff, value); +    *p += ret; +    return 1; +} + +/* Return 1 if the character is permitted in a PrintableString */ +static int is_printable(unsigned long value) +{ +    int ch; +    if (value > 0x7f) +        return 0; +    ch = (int)value; +    /* +     * Note: we can't use 'isalnum' because certain accented characters may +     * count as alphanumeric in some environments. +     */ +#ifndef CHARSET_EBCDIC +    if ((ch >= 'a') && (ch <= 'z')) +        return 1; +    if ((ch >= 'A') && (ch <= 'Z')) +        return 1; +    if ((ch >= '0') && (ch <= '9')) +        return 1; +    if ((ch == ' ') || strchr("'()+,-./:=?", ch)) +        return 1; +#else                           /* CHARSET_EBCDIC */ +    if ((ch >= os_toascii['a']) && (ch <= os_toascii['z'])) +        return 1; +    if ((ch >= os_toascii['A']) && (ch <= os_toascii['Z'])) +        return 1; +    if ((ch >= os_toascii['0']) && (ch <= os_toascii['9'])) +        return 1; +    if ((ch == os_toascii[' ']) || strchr("'()+,-./:=?", os_toebcdic[ch])) +        return 1; +#endif                          /* CHARSET_EBCDIC */ +    return 0; +} + +/* Return 1 if the character is a digit or space */ +static int is_numeric(unsigned long value) +{ +    int ch; +    if (value > 0x7f) +        return 0; +    ch = (int)value; +#ifndef CHARSET_EBCDIC +    if (!isdigit(ch) && ch != ' ') +        return 0; +#else +    if (ch > os_toascii['9']) +        return 0; +    if (ch < os_toascii['0'] && ch != os_toascii[' ']) +        return 0; +#endif +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/a_object.c b/openssl-1.1.0h/crypto/asn1/a_object.c new file mode 100644 index 0000000..1ec7a7e --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_object.c @@ -0,0 +1,370 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <limits.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/asn1.h> +#include <openssl/objects.h> +#include <openssl/bn.h> +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +int i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) +{ +    unsigned char *p; +    int objsize; + +    if ((a == NULL) || (a->data == NULL)) +        return (0); + +    objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT); +    if (pp == NULL || objsize == -1) +        return objsize; + +    p = *pp; +    ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL); +    memcpy(p, a->data, a->length); +    p += a->length; + +    *pp = p; +    return (objsize); +} + +int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) +{ +    int i, first, len = 0, c, use_bn; +    char ftmp[24], *tmp = ftmp; +    int tmpsize = sizeof(ftmp); +    const char *p; +    unsigned long l; +    BIGNUM *bl = NULL; + +    if (num == 0) +        return (0); +    else if (num == -1) +        num = strlen(buf); + +    p = buf; +    c = *(p++); +    num--; +    if ((c >= '0') && (c <= '2')) { +        first = c - '0'; +    } else { +        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_FIRST_NUM_TOO_LARGE); +        goto err; +    } + +    if (num <= 0) { +        ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_MISSING_SECOND_NUMBER); +        goto err; +    } +    c = *(p++); +    num--; +    for (;;) { +        if (num <= 0) +            break; +        if ((c != '.') && (c != ' ')) { +            ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_SEPARATOR); +            goto err; +        } +        l = 0; +        use_bn = 0; +        for (;;) { +            if (num <= 0) +                break; +            num--; +            c = *(p++); +            if ((c == ' ') || (c == '.')) +                break; +            if ((c < '0') || (c > '9')) { +                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_INVALID_DIGIT); +                goto err; +            } +            if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { +                use_bn = 1; +                if (bl == NULL) +                    bl = BN_new(); +                if (bl == NULL || !BN_set_word(bl, l)) +                    goto err; +            } +            if (use_bn) { +                if (!BN_mul_word(bl, 10L) +                    || !BN_add_word(bl, c - '0')) +                    goto err; +            } else +                l = l * 10L + (long)(c - '0'); +        } +        if (len == 0) { +            if ((first < 2) && (l >= 40)) { +                ASN1err(ASN1_F_A2D_ASN1_OBJECT, +                        ASN1_R_SECOND_NUMBER_TOO_LARGE); +                goto err; +            } +            if (use_bn) { +                if (!BN_add_word(bl, first * 40)) +                    goto err; +            } else +                l += (long)first *40; +        } +        i = 0; +        if (use_bn) { +            int blsize; +            blsize = BN_num_bits(bl); +            blsize = (blsize + 6) / 7; +            if (blsize > tmpsize) { +                if (tmp != ftmp) +                    OPENSSL_free(tmp); +                tmpsize = blsize + 32; +                tmp = OPENSSL_malloc(tmpsize); +                if (tmp == NULL) +                    goto err; +            } +            while (blsize--) { +                BN_ULONG t = BN_div_word(bl, 0x80L); +                if (t == (BN_ULONG)-1) +                    goto err; +                tmp[i++] = (unsigned char)t; +            } +        } else { + +            for (;;) { +                tmp[i++] = (unsigned char)l & 0x7f; +                l >>= 7L; +                if (l == 0L) +                    break; +            } + +        } +        if (out != NULL) { +            if (len + i > olen) { +                ASN1err(ASN1_F_A2D_ASN1_OBJECT, ASN1_R_BUFFER_TOO_SMALL); +                goto err; +            } +            while (--i > 0) +                out[len++] = tmp[i] | 0x80; +            out[len++] = tmp[0]; +        } else +            len += i; +    } +    if (tmp != ftmp) +        OPENSSL_free(tmp); +    BN_free(bl); +    return (len); + err: +    if (tmp != ftmp) +        OPENSSL_free(tmp); +    BN_free(bl); +    return (0); +} + +int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) +{ +    return OBJ_obj2txt(buf, buf_len, a, 0); +} + +int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) +{ +    char buf[80], *p = buf; +    int i; + +    if ((a == NULL) || (a->data == NULL)) +        return (BIO_write(bp, "NULL", 4)); +    i = i2t_ASN1_OBJECT(buf, sizeof(buf), a); +    if (i > (int)(sizeof(buf) - 1)) { +        p = OPENSSL_malloc(i + 1); +        if (p == NULL) +            return -1; +        i2t_ASN1_OBJECT(p, i + 1, a); +    } +    if (i <= 0) { +        i = BIO_write(bp, "<INVALID>", 9); +        i += BIO_dump(bp, (const char *)a->data, a->length); +        return i; +    } +    BIO_write(bp, p, i); +    if (p != buf) +        OPENSSL_free(p); +    return (i); +} + +ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, +                             long length) +{ +    const unsigned char *p; +    long len; +    int tag, xclass; +    int inf, i; +    ASN1_OBJECT *ret = NULL; +    p = *pp; +    inf = ASN1_get_object(&p, &len, &tag, &xclass, length); +    if (inf & 0x80) { +        i = ASN1_R_BAD_OBJECT_HEADER; +        goto err; +    } + +    if (tag != V_ASN1_OBJECT) { +        i = ASN1_R_EXPECTING_AN_OBJECT; +        goto err; +    } +    ret = c2i_ASN1_OBJECT(a, &p, len); +    if (ret) +        *pp = p; +    return ret; + err: +    ASN1err(ASN1_F_D2I_ASN1_OBJECT, i); +    return (NULL); +} + +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, +                             long len) +{ +    ASN1_OBJECT *ret = NULL, tobj; +    const unsigned char *p; +    unsigned char *data; +    int i, length; + +    /* +     * Sanity check OID encoding. Need at least one content octet. MSB must +     * be clear in the last octet. can't have leading 0x80 in subidentifiers, +     * see: X.690 8.19.2 +     */ +    if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL || +        p[len - 1] & 0x80) { +        ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); +        return NULL; +    } +    /* Now 0 < len <= INT_MAX, so the cast is safe. */ +    length = (int)len; +    /* +     * Try to lookup OID in table: these are all valid encodings so if we get +     * a match we know the OID is valid. +     */ +    tobj.nid = NID_undef; +    tobj.data = p; +    tobj.length = length; +    tobj.flags = 0; +    i = OBJ_obj2nid(&tobj); +    if (i != NID_undef) { +        /* +         * Return shared registered OID object: this improves efficiency +         * because we don't have to return a dynamically allocated OID +         * and NID lookups can use the cached value. +         */ +        ret = OBJ_nid2obj(i); +        if (a) { +            ASN1_OBJECT_free(*a); +            *a = ret; +        } +        *pp += len; +        return ret; +    } +    for (i = 0; i < length; i++, p++) { +        if (*p == 0x80 && (!i || !(p[-1] & 0x80))) { +            ASN1err(ASN1_F_C2I_ASN1_OBJECT, ASN1_R_INVALID_OBJECT_ENCODING); +            return NULL; +        } +    } + +    /* +     * only the ASN1_OBJECTs from the 'table' will have values for ->sn or +     * ->ln +     */ +    if ((a == NULL) || ((*a) == NULL) || +        !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) { +        if ((ret = ASN1_OBJECT_new()) == NULL) +            return (NULL); +    } else +        ret = (*a); + +    p = *pp; +    /* detach data from object */ +    data = (unsigned char *)ret->data; +    ret->data = NULL; +    /* once detached we can change it */ +    if ((data == NULL) || (ret->length < length)) { +        ret->length = 0; +        OPENSSL_free(data); +        data = OPENSSL_malloc(length); +        if (data == NULL) { +            i = ERR_R_MALLOC_FAILURE; +            goto err; +        } +        ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA; +    } +    memcpy(data, p, length); +    /* reattach data to object, after which it remains const */ +    ret->data = data; +    ret->length = length; +    ret->sn = NULL; +    ret->ln = NULL; +    /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */ +    p += length; + +    if (a != NULL) +        (*a) = ret; +    *pp = p; +    return (ret); + err: +    ASN1err(ASN1_F_C2I_ASN1_OBJECT, i); +    if ((a == NULL) || (*a != ret)) +        ASN1_OBJECT_free(ret); +    return (NULL); +} + +ASN1_OBJECT *ASN1_OBJECT_new(void) +{ +    ASN1_OBJECT *ret; + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) { +        ASN1err(ASN1_F_ASN1_OBJECT_NEW, ERR_R_MALLOC_FAILURE); +        return (NULL); +    } +    ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; +    return (ret); +} + +void ASN1_OBJECT_free(ASN1_OBJECT *a) +{ +    if (a == NULL) +        return; +    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { +#ifndef CONST_STRICT            /* disable purely for compile-time strict +                                 * const checking. Doing this on a "real" +                                 * compile will cause memory leaks */ +        OPENSSL_free((void*)a->sn); +        OPENSSL_free((void*)a->ln); +#endif +        a->sn = a->ln = NULL; +    } +    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { +        OPENSSL_free((void*)a->data); +        a->data = NULL; +        a->length = 0; +    } +    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) +        OPENSSL_free(a); +} + +ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, +                                const char *sn, const char *ln) +{ +    ASN1_OBJECT o; + +    o.sn = sn; +    o.ln = ln; +    o.data = data; +    o.nid = nid; +    o.length = len; +    o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | +        ASN1_OBJECT_FLAG_DYNAMIC_DATA; +    return (OBJ_dup(&o)); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_octet.c b/openssl-1.1.0h/crypto/asn1/a_octet.c new file mode 100644 index 0000000..2e1205c --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_octet.c @@ -0,0 +1,29 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x) +{ +    return ASN1_STRING_dup(x); +} + +int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, +                          const ASN1_OCTET_STRING *b) +{ +    return ASN1_STRING_cmp(a, b); +} + +int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, +                          int len) +{ +    return ASN1_STRING_set(x, d, len); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_print.c b/openssl-1.1.0h/crypto/asn1/a_print.c new file mode 100644 index 0000000..1aafe7c --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_print.c @@ -0,0 +1,109 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +int ASN1_PRINTABLE_type(const unsigned char *s, int len) +{ +    int c; +    int ia5 = 0; +    int t61 = 0; + +    if (len <= 0) +        len = -1; +    if (s == NULL) +        return (V_ASN1_PRINTABLESTRING); + +    while ((*s) && (len-- != 0)) { +        c = *(s++); +#ifndef CHARSET_EBCDIC +        if (!(((c >= 'a') && (c <= 'z')) || +              ((c >= 'A') && (c <= 'Z')) || +              ((c >= '0') && (c <= '9')) || +              (c == ' ') || (c == '\'') || +              (c == '(') || (c == ')') || +              (c == '+') || (c == ',') || +              (c == '-') || (c == '.') || +              (c == '/') || (c == ':') || (c == '=') || (c == '?'))) +            ia5 = 1; +        if (c & 0x80) +            t61 = 1; +#else +        if (!isalnum(c) && (c != ' ') && strchr("'()+,-./:=?", c) == NULL) +            ia5 = 1; +        if (os_toascii[c] & 0x80) +            t61 = 1; +#endif +    } +    if (t61) +        return (V_ASN1_T61STRING); +    if (ia5) +        return (V_ASN1_IA5STRING); +    return (V_ASN1_PRINTABLESTRING); +} + +int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s) +{ +    int i; +    unsigned char *p; + +    if (s->type != V_ASN1_UNIVERSALSTRING) +        return (0); +    if ((s->length % 4) != 0) +        return (0); +    p = s->data; +    for (i = 0; i < s->length; i += 4) { +        if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0')) +            break; +        else +            p += 4; +    } +    if (i < s->length) +        return (0); +    p = s->data; +    for (i = 3; i < s->length; i += 4) { +        *(p++) = s->data[i]; +    } +    *(p) = '\0'; +    s->length /= 4; +    s->type = ASN1_PRINTABLE_type(s->data, s->length); +    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); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_sign.c b/openssl-1.1.0h/crypto/asn1/a_sign.c new file mode 100644 index 0000000..3b261eb --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_sign.c @@ -0,0 +1,225 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> + +#include "internal/cryptlib.h" + +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +#ifndef NO_ASN1_OLD + +int ASN1_sign(i2d_of_void *i2d, X509_ALGOR *algor1, X509_ALGOR *algor2, +              ASN1_BIT_STRING *signature, char *data, EVP_PKEY *pkey, +              const EVP_MD *type) +{ +    EVP_MD_CTX *ctx = EVP_MD_CTX_new(); +    unsigned char *p, *buf_in = NULL, *buf_out = NULL; +    int i, inl = 0, outl = 0, outll = 0; +    X509_ALGOR *a; + +    if (ctx == NULL) { +        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    for (i = 0; i < 2; i++) { +        if (i == 0) +            a = algor1; +        else +            a = algor2; +        if (a == NULL) +            continue; +        if (type->pkey_type == NID_dsaWithSHA1) { +            /* +             * special case: RFC 2459 tells us to omit 'parameters' with +             * id-dsa-with-sha1 +             */ +            ASN1_TYPE_free(a->parameter); +            a->parameter = NULL; +        } else if ((a->parameter == NULL) || +                   (a->parameter->type != V_ASN1_NULL)) { +            ASN1_TYPE_free(a->parameter); +            if ((a->parameter = ASN1_TYPE_new()) == NULL) +                goto err; +            a->parameter->type = V_ASN1_NULL; +        } +        ASN1_OBJECT_free(a->algorithm); +        a->algorithm = OBJ_nid2obj(type->pkey_type); +        if (a->algorithm == NULL) { +            ASN1err(ASN1_F_ASN1_SIGN, ASN1_R_UNKNOWN_OBJECT_TYPE); +            goto err; +        } +        if (a->algorithm->length == 0) { +            ASN1err(ASN1_F_ASN1_SIGN, +                    ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); +            goto err; +        } +    } +    inl = i2d(data, NULL); +    buf_in = OPENSSL_malloc((unsigned int)inl); +    outll = outl = EVP_PKEY_size(pkey); +    buf_out = OPENSSL_malloc((unsigned int)outl); +    if ((buf_in == NULL) || (buf_out == NULL)) { +        outl = 0; +        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    p = buf_in; + +    i2d(data, &p); +    if (!EVP_SignInit_ex(ctx, type, NULL) +        || !EVP_SignUpdate(ctx, (unsigned char *)buf_in, inl) +        || !EVP_SignFinal(ctx, (unsigned char *)buf_out, +                          (unsigned int *)&outl, pkey)) { +        outl = 0; +        ASN1err(ASN1_F_ASN1_SIGN, ERR_R_EVP_LIB); +        goto err; +    } +    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_free(ctx); +    OPENSSL_clear_free((char *)buf_in, (unsigned int)inl); +    OPENSSL_clear_free((char *)buf_out, outll); +    return (outl); +} + +#endif + +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) +{ +    int rv; +    EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + +    if (ctx == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_SIGN, ERR_R_MALLOC_FAILURE); +        return 0; +    } +    if (!EVP_DigestSignInit(ctx, NULL, type, NULL, pkey)) { +        EVP_MD_CTX_free(ctx); +        return 0; +    } + +    rv = ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, ctx); + +    EVP_MD_CTX_free(ctx); +    return rv; +} + +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) +{ +    const EVP_MD *type; +    EVP_PKEY *pkey; +    unsigned char *buf_in = NULL, *buf_out = NULL; +    size_t inl = 0, outl = 0, outll = 0; +    int signid, paramtype; +    int rv; + +    type = EVP_MD_CTX_md(ctx); +    pkey = EVP_PKEY_CTX_get0_pkey(EVP_MD_CTX_pkey_ctx(ctx)); + +    if (type == NULL || pkey == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_CONTEXT_NOT_INITIALISED); +        goto err; +    } + +    if (pkey->ameth == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); +        goto err; +    } + +    if (pkey->ameth->item_sign) { +        rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, signature); +        if (rv == 1) +            outl = signature->length; +        /*- +         * Return value meanings: +         * <=0: error. +         *   1: method does everything. +         *   2: carry on as normal. +         *   3: ASN1 method sets algorithm identifiers: just sign. +         */ +        if (rv <= 0) +            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); +        if (rv <= 1) +            goto err; +    } else +        rv = 2; + +    if (rv == 2) { +        if (!OBJ_find_sigid_by_algs(&signid, +                                    EVP_MD_nid(type), +                                    pkey->ameth->pkey_id)) { +            ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, +                    ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); +            goto err; +        } + +        if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) +            paramtype = V_ASN1_NULL; +        else +            paramtype = V_ASN1_UNDEF; + +        if (algor1) +            X509_ALGOR_set0(algor1, OBJ_nid2obj(signid), paramtype, NULL); +        if (algor2) +            X509_ALGOR_set0(algor2, OBJ_nid2obj(signid), paramtype, NULL); + +    } + +    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; +        ASN1err(ASN1_F_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; +        ASN1err(ASN1_F_ASN1_ITEM_SIGN_CTX, ERR_R_EVP_LIB); +        goto err; +    } +    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: +    OPENSSL_clear_free((char *)buf_in, (unsigned int)inl); +    OPENSSL_clear_free((char *)buf_out, outll); +    return (outl); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_strex.c b/openssl-1.1.0h/crypto/asn1/a_strex.c new file mode 100644 index 0000000..b91266b --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_strex.c @@ -0,0 +1,644 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <string.h> +#include "internal/cryptlib.h" +#include "internal/asn1_int.h" +#include <openssl/crypto.h> +#include <openssl/x509.h> +#include <openssl/asn1.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_2254 | \ +                  ASN1_STRFLGS_ESC_QUOTE | \ +                  ASN1_STRFLGS_ESC_CTRL | \ +                  ASN1_STRFLGS_ESC_MSB) + +/* + * Three IO functions for sending data to memory, a BIO and and a FILE + * pointer. + */ +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; +} + +#ifndef OPENSSL_NO_STDIO +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; +} +#endif + +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. + */ + +static int do_esc_char(unsigned long c, unsigned short flags, char *do_quotes, +                       char_io *io_ch, void *arg) +{ +    unsigned short chflgs; +    unsigned char 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 +                  | ASN1_STRFLGS_ESC_2254)) { +        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 short flags, char *quotes, char_io *io_ch, +                  void *arg) +{ +    int i, outlen, len; +    unsigned short orflags; +    unsigned char *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], flags | orflags, quotes, +                                  io_ch, arg); +                if (len < 0) +                    return -1; +                outlen += len; +            } +        } else { +            len = do_esc_char(c, 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, +                   const 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 == NULL) +        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, +                       const ASN1_STRING *str) +{ +    int outlen, len; +    int type; +    char quotes; +    unsigned short flags; +    quotes = 0; +    /* Keep a copy of escape flags */ +    flags = (unsigned short)(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, "es, 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, const X509_NAME *n, +                      int indent, unsigned long flags) +{ +    int i, prev = -1, orflags, cnt; +    int fn_opt, fn_nid; +    ASN1_OBJECT *fn; +    const ASN1_STRING *val; +    const X509_NAME_ENTRY *ent; +    char objtmp[80]; +    const char *objbuf; +    int outlen, len; +    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 == X509_NAME_ENTRY_set(ent)) { +                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 = X509_NAME_ENTRY_set(ent); +        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, const 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_STDIO +int X509_NAME_print_ex_fp(FILE *fp, const 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, const ASN1_STRING *str, unsigned long flags) +{ +    return do_print_ex(send_bio_chars, out, flags, str); +} + +#ifndef OPENSSL_NO_STDIO +int ASN1_STRING_print_ex_fp(FILE *fp, const 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, const 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; +} + +/* Return 1 if host is a valid hostname and 0 otherwise */ +int asn1_valid_host(const ASN1_STRING *host) +{ +    int hostlen = host->length; +    const unsigned char *hostptr = host->data; +    int type = host->type; +    int i; +    signed char width = -1; +    unsigned short chflags = 0, prevchflags; + +    if (type > 0 && type < 31) +        width = tag2nbyte[type]; +    if (width == -1 || hostlen == 0) +        return 0; +    /* Treat UTF8String as width 1 as any MSB set is invalid */ +    if (width == 0) +        width = 1; +    for (i = 0 ; i < hostlen; i+= width) { +        prevchflags = chflags; +        /* Value must be <= 0x7F: check upper bytes are all zeroes */ +        if (width == 4) { +            if (*hostptr++ != 0 || *hostptr++ != 0 || *hostptr++ != 0) +                return 0; +        } else if (width == 2) { +            if (*hostptr++ != 0) +                return 0; +        } +        if (*hostptr > 0x7f) +            return 0; +        chflags = char_type[*hostptr++]; +        if (!(chflags & (CHARTYPE_HOST_ANY | CHARTYPE_HOST_WILD))) { +            /* Nothing else allowed at start or end of string */ +            if (i == 0 || i == hostlen - 1) +                return 0; +            /* Otherwise invalid if not dot or hyphen */ +            if (!(chflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN))) +                return 0; +            /* +             * If previous is dot or hyphen then illegal unless both +             * are hyphens: as .- -. .. are all illegal +             */ +            if (prevchflags & (CHARTYPE_HOST_DOT | CHARTYPE_HOST_HYPHEN) +                && ((prevchflags & CHARTYPE_HOST_DOT) +                    || (chflags & CHARTYPE_HOST_DOT))) +                return 0; +        } +    } +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/a_strnid.c b/openssl-1.1.0h/crypto/asn1/a_strnid.c new file mode 100644 index 0000000..ecf178e --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_strnid.c @@ -0,0 +1,289 @@ +/* + * Copyright 1999-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/objects.h> + +static STACK_OF(ASN1_STRING_TABLE) *stable = NULL; +static void st_free(ASN1_STRING_TABLE *tbl); +static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, +                        const ASN1_STRING_TABLE *const *b); + +/* + * This is the global mask for the mbstring functions: this is use to mask + * out certain types (such as BMPString and UTF8String) because certain + * software (e.g. Netscape) has problems with them. + */ + +static unsigned long global_mask = B_ASN1_UTF8STRING; + +void ASN1_STRING_set_default_mask(unsigned long mask) +{ +    global_mask = mask; +} + +unsigned long ASN1_STRING_get_default_mask(void) +{ +    return global_mask; +} + +/*- + * This function sets the default to various "flavours" of configuration. + * based on an ASCII string. Currently this is: + * MASK:XXXX : a numerical mask value. + * nobmp : Don't use BMPStrings (just Printable, T61). + * pkix : PKIX recommendation in RFC2459. + * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004). + * default:   the default value, Printable, T61, BMP. + */ + +int ASN1_STRING_set_default_mask_asc(const char *p) +{ +    unsigned long mask; +    char *end; +    if (strncmp(p, "MASK:", 5) == 0) { +        if (!p[5]) +            return 0; +        mask = strtoul(p + 5, &end, 0); +        if (*end) +            return 0; +    } else if (strcmp(p, "nombstr") == 0) +        mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING)); +    else if (strcmp(p, "pkix") == 0) +        mask = ~((unsigned long)B_ASN1_T61STRING); +    else if (strcmp(p, "utf8only") == 0) +        mask = B_ASN1_UTF8STRING; +    else if (strcmp(p, "default") == 0) +        mask = 0xFFFFFFFFL; +    else +        return 0; +    ASN1_STRING_set_default_mask(mask); +    return 1; +} + +/* + * The following function generates an ASN1_STRING based on limits in a + * table. Frequently the types and length of an ASN1_STRING are restricted by + * a corresponding OID. For example certificates and certificate requests. + */ + +ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, +                                    const unsigned char *in, int inlen, +                                    int inform, int nid) +{ +    ASN1_STRING_TABLE *tbl; +    ASN1_STRING *str = NULL; +    unsigned long mask; +    int ret; +    if (!out) +        out = &str; +    tbl = ASN1_STRING_TABLE_get(nid); +    if (tbl) { +        mask = tbl->mask; +        if (!(tbl->flags & STABLE_NO_MASK)) +            mask &= global_mask; +        ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask, +                                  tbl->minsize, tbl->maxsize); +    } else +        ret = +            ASN1_mbstring_copy(out, in, inlen, inform, +                               DIRSTRING_TYPE & global_mask); +    if (ret <= 0) +        return NULL; +    return *out; +} + +/* + * Now the tables and helper functions for the string table: + */ + +/* size limits: this stuff is taken straight from RFC3280 */ + +#define ub_name                         32768 +#define ub_common_name                  64 +#define ub_locality_name                128 +#define ub_state_name                   128 +#define ub_organization_name            64 +#define ub_organization_unit_name       64 +#define ub_title                        64 +#define ub_email_address                128 +#define ub_serial_number                64 + +/* From RFC4524 */ + +#define ub_rfc822_mailbox               256 + +/* This table must be kept in NID order */ + +static const ASN1_STRING_TABLE tbl_standard[] = { +    {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0}, +    {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, +    {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0}, +    {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0}, +    {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0}, +    {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE, +     0}, +    {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING, +     STABLE_NO_MASK}, +    {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0}, +    {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0}, +    {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0}, +    {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0}, +    {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0}, +    {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0}, +    {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING, +     STABLE_NO_MASK}, +    {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, +    {NID_name, 1, ub_name, DIRSTRING_TYPE, 0}, +    {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, +    {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK}, +    {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}, +    {NID_rfc822Mailbox, 1, ub_rfc822_mailbox, B_ASN1_IA5STRING, +     STABLE_NO_MASK}, +    {NID_jurisdictionCountryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK}, +    {NID_INN, 1, 12, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, +    {NID_OGRN, 1, 13, B_ASN1_NUMERICSTRING, STABLE_NO_MASK}, +    {NID_SNILS, 1, 11, B_ASN1_NUMERICSTRING, STABLE_NO_MASK} +}; + +static int sk_table_cmp(const ASN1_STRING_TABLE *const *a, +                        const ASN1_STRING_TABLE *const *b) +{ +    return (*a)->nid - (*b)->nid; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); + +static int table_cmp(const ASN1_STRING_TABLE *a, const ASN1_STRING_TABLE *b) +{ +    return a->nid - b->nid; +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(ASN1_STRING_TABLE, ASN1_STRING_TABLE, table); + +ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid) +{ +    int idx; +    ASN1_STRING_TABLE fnd; +    fnd.nid = nid; +    if (stable) { +        idx = sk_ASN1_STRING_TABLE_find(stable, &fnd); +        if (idx >= 0) +            return sk_ASN1_STRING_TABLE_value(stable, idx); +    } +    return OBJ_bsearch_table(&fnd, tbl_standard, OSSL_NELEM(tbl_standard)); +} + +/* + * Return a string table pointer which can be modified: either directly from + * table or a copy of an internal value added to the table. + */ + +static ASN1_STRING_TABLE *stable_get(int nid) +{ +    ASN1_STRING_TABLE *tmp, *rv; +    /* Always need a string table so allocate one if NULL */ +    if (stable == NULL) { +        stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp); +        if (stable == NULL) +            return NULL; +    } +    tmp = ASN1_STRING_TABLE_get(nid); +    if (tmp && tmp->flags & STABLE_FLAGS_MALLOC) +        return tmp; +    rv = OPENSSL_zalloc(sizeof(*rv)); +    if (rv == NULL) +        return NULL; +    if (!sk_ASN1_STRING_TABLE_push(stable, rv)) { +        OPENSSL_free(rv); +        return NULL; +    } +    if (tmp) { +        rv->nid = tmp->nid; +        rv->minsize = tmp->minsize; +        rv->maxsize = tmp->maxsize; +        rv->mask = tmp->mask; +        rv->flags = tmp->flags | STABLE_FLAGS_MALLOC; +    } else { +        rv->nid = nid; +        rv->minsize = -1; +        rv->maxsize = -1; +        rv->flags = STABLE_FLAGS_MALLOC; +    } +    return rv; +} + +int ASN1_STRING_TABLE_add(int nid, +                          long minsize, long maxsize, unsigned long mask, +                          unsigned long flags) +{ +    ASN1_STRING_TABLE *tmp; +    tmp = stable_get(nid); +    if (!tmp) { +        ASN1err(ASN1_F_ASN1_STRING_TABLE_ADD, ERR_R_MALLOC_FAILURE); +        return 0; +    } +    if (minsize >= 0) +        tmp->minsize = minsize; +    if (maxsize >= 0) +        tmp->maxsize = maxsize; +    if (mask) +        tmp->mask = mask; +    if (flags) +        tmp->flags = STABLE_FLAGS_MALLOC | flags; +    return 1; +} + +void ASN1_STRING_TABLE_cleanup(void) +{ +    STACK_OF(ASN1_STRING_TABLE) *tmp; +    tmp = stable; +    if (!tmp) +        return; +    stable = NULL; +    sk_ASN1_STRING_TABLE_pop_free(tmp, st_free); +} + +static void st_free(ASN1_STRING_TABLE *tbl) +{ +    if (tbl->flags & STABLE_FLAGS_MALLOC) +        OPENSSL_free(tbl); +} + + +#ifdef STRING_TABLE_TEST + +main() +{ +    ASN1_STRING_TABLE *tmp; +    int i, last_nid = -1; + +    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) { +        if (tmp->nid < last_nid) { +            last_nid = 0; +            break; +        } +        last_nid = tmp->nid; +    } + +    if (last_nid != 0) { +        printf("Table order OK\n"); +        exit(0); +    } + +    for (tmp = tbl_standard, i = 0; i < OSSL_NELEM(tbl_standard); i++, tmp++) +        printf("Index %d, NID %d, Name=%s\n", i, tmp->nid, +               OBJ_nid2ln(tmp->nid)); + +} + +#endif diff --git a/openssl-1.1.0h/crypto/asn1/a_time.c b/openssl-1.1.0h/crypto/asn1/a_time.c new file mode 100644 index 0000000..46f539c --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_time.c @@ -0,0 +1,170 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/*- + * This is an implementation of the ASN1 Time structure which is: + *    Time ::= CHOICE { + *      utcTime        UTCTime, + *      generalTime    GeneralizedTime } + */ + +#include <stdio.h> +#include <time.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include "asn1_locl.h" + +IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME) + +IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME) + +ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t) +{ +    return ASN1_TIME_adj(s, t, 0, 0); +} + +ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, +                         int offset_day, long offset_sec) +{ +    struct tm *ts; +    struct tm data; + +    ts = OPENSSL_gmtime(&t, &data); +    if (ts == NULL) { +        ASN1err(ASN1_F_ASN1_TIME_ADJ, ASN1_R_ERROR_GETTING_TIME); +        return NULL; +    } +    if (offset_day || offset_sec) { +        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) +            return NULL; +    } +    if ((ts->tm_year >= 50) && (ts->tm_year < 150)) +        return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec); +    return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec); +} + +int ASN1_TIME_check(const ASN1_TIME *t) +{ +    if (t->type == V_ASN1_GENERALIZEDTIME) +        return ASN1_GENERALIZEDTIME_check(t); +    else if (t->type == V_ASN1_UTCTIME) +        return ASN1_UTCTIME_check(t); +    return 0; +} + +/* Convert an ASN1_TIME structure to GeneralizedTime */ +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *t, +                                                   ASN1_GENERALIZEDTIME **out) +{ +    ASN1_GENERALIZEDTIME *ret = NULL; +    char *str; +    int newlen; + +    if (!ASN1_TIME_check(t)) +        return NULL; + +    if (out == NULL || *out == NULL) { +        if ((ret = ASN1_GENERALIZEDTIME_new()) == NULL) +            goto err; +    } else +        ret = *out; + +    /* If already GeneralizedTime just copy across */ +    if (t->type == V_ASN1_GENERALIZEDTIME) { +        if (!ASN1_STRING_set(ret, t->data, t->length)) +            goto err; +        goto done; +    } + +    /* grow the string */ +    if (!ASN1_STRING_set(ret, NULL, t->length + 2)) +        goto err; +    /* ASN1_STRING_set() allocated 'len + 1' bytes. */ +    newlen = t->length + 2 + 1; +    str = (char *)ret->data; +    /* Work out the century and prepend */ +    if (t->data[0] >= '5') +        OPENSSL_strlcpy(str, "19", newlen); +    else +        OPENSSL_strlcpy(str, "20", newlen); + +    OPENSSL_strlcat(str, (const char *)t->data, newlen); + + done: +   if (out != NULL && *out == NULL) +       *out = ret; +   return ret; + + err: +    if (out == NULL || *out != ret) +        ASN1_GENERALIZEDTIME_free(ret); +    return NULL; +} + + +int ASN1_TIME_set_string(ASN1_TIME *s, const char *str) +{ +    ASN1_TIME t; + +    t.length = strlen(str); +    t.data = (unsigned char *)str; +    t.flags = 0; + +    t.type = V_ASN1_UTCTIME; + +    if (!ASN1_TIME_check(&t)) { +        t.type = V_ASN1_GENERALIZEDTIME; +        if (!ASN1_TIME_check(&t)) +            return 0; +    } + +    if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t)) +        return 0; + +    return 1; +} + +static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t) +{ +    if (t == NULL) { +        time_t now_t; +        time(&now_t); +        if (OPENSSL_gmtime(&now_t, tm)) +            return 1; +        return 0; +    } + +    if (t->type == V_ASN1_UTCTIME) +        return asn1_utctime_to_tm(tm, t); +    else if (t->type == V_ASN1_GENERALIZEDTIME) +        return asn1_generalizedtime_to_tm(tm, t); + +    return 0; +} + +int ASN1_TIME_diff(int *pday, int *psec, +                   const ASN1_TIME *from, const ASN1_TIME *to) +{ +    struct tm tm_from, tm_to; +    if (!asn1_time_to_tm(&tm_from, from)) +        return 0; +    if (!asn1_time_to_tm(&tm_to, to)) +        return 0; +    return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to); +} + +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); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_type.c b/openssl-1.1.0h/crypto/asn1/a_type.c new file mode 100644 index 0000000..df42360 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_type.c @@ -0,0 +1,134 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include "asn1_locl.h" + +int ASN1_TYPE_get(const ASN1_TYPE *a) +{ +    if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL)) +        return (a->type); +    else +        return (0); +} + +void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value) +{ +    if (a->value.ptr != NULL) { +        ASN1_TYPE **tmp_a = &a; +        asn1_primitive_free((ASN1_VALUE **)tmp_a, NULL, 0); +    } +    a->type = type; +    if (type == V_ASN1_BOOLEAN) +        a->value.boolean = value ? 0xff : 0; +    else +        a->value.ptr = value; +} + +int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value) +{ +    if (!value || (type == V_ASN1_BOOLEAN)) { +        void *p = (void *)value; +        ASN1_TYPE_set(a, type, p); +    } else if (type == V_ASN1_OBJECT) { +        ASN1_OBJECT *odup; +        odup = OBJ_dup(value); +        if (!odup) +            return 0; +        ASN1_TYPE_set(a, type, odup); +    } else { +        ASN1_STRING *sdup; +        sdup = ASN1_STRING_dup(value); +        if (!sdup) +            return 0; +        ASN1_TYPE_set(a, type, sdup); +    } +    return 1; +} + +/* Returns 0 if they are equal, != 0 otherwise. */ +int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b) +{ +    int result = -1; + +    if (!a || !b || a->type != b->type) +        return -1; + +    switch (a->type) { +    case V_ASN1_OBJECT: +        result = OBJ_cmp(a->value.object, b->value.object); +        break; +    case V_ASN1_BOOLEAN: +        result = a->value.boolean - b->value.boolean; +        break; +    case V_ASN1_NULL: +        result = 0;             /* They do not have content. */ +        break; +    case V_ASN1_INTEGER: +    case V_ASN1_ENUMERATED: +    case V_ASN1_BIT_STRING: +    case V_ASN1_OCTET_STRING: +    case V_ASN1_SEQUENCE: +    case V_ASN1_SET: +    case V_ASN1_NUMERICSTRING: +    case V_ASN1_PRINTABLESTRING: +    case V_ASN1_T61STRING: +    case V_ASN1_VIDEOTEXSTRING: +    case V_ASN1_IA5STRING: +    case V_ASN1_UTCTIME: +    case V_ASN1_GENERALIZEDTIME: +    case V_ASN1_GRAPHICSTRING: +    case V_ASN1_VISIBLESTRING: +    case V_ASN1_GENERALSTRING: +    case V_ASN1_UNIVERSALSTRING: +    case V_ASN1_BMPSTRING: +    case V_ASN1_UTF8STRING: +    case V_ASN1_OTHER: +    default: +        result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr, +                                 (ASN1_STRING *)b->value.ptr); +        break; +    } + +    return result; +} + +ASN1_TYPE *ASN1_TYPE_pack_sequence(const ASN1_ITEM *it, void *s, ASN1_TYPE **t) +{ +    ASN1_OCTET_STRING *oct; +    ASN1_TYPE *rt; + +    oct = ASN1_item_pack(s, it, NULL); +    if (oct == NULL) +        return NULL; + +    if (t && *t) { +        rt = *t; +    } else { +        rt = ASN1_TYPE_new(); +        if (rt == NULL) { +            ASN1_OCTET_STRING_free(oct); +            return NULL; +        } +        if (t) +            *t = rt; +    } +    ASN1_TYPE_set(rt, V_ASN1_SEQUENCE, oct); +    return rt; +} + +void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t) +{ +    if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL) +        return NULL; +    return ASN1_item_unpack(t->value.sequence, it); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_utctm.c b/openssl-1.1.0h/crypto/asn1/a_utctm.c new file mode 100644 index 0000000..9797aa8 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_utctm.c @@ -0,0 +1,254 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <time.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include "asn1_locl.h" + +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d) +{ +    static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 }; +    static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 }; +    char *a; +    int n, i, l, o; + +    if (d->type != V_ASN1_UTCTIME) +        return (0); +    l = d->length; +    a = (char *)d->data; +    o = 0; + +    if (l < 11) +        goto err; +    for (i = 0; i < 6; i++) { +        if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) { +            i++; +            if (tm) +                tm->tm_sec = 0; +            break; +        } +        if ((a[o] < '0') || (a[o] > '9')) +            goto err; +        n = a[o] - '0'; +        if (++o > l) +            goto err; + +        if ((a[o] < '0') || (a[o] > '9')) +            goto err; +        n = (n * 10) + a[o] - '0'; +        if (++o > l) +            goto err; + +        if ((n < min[i]) || (n > max[i])) +            goto err; +        if (tm) { +            switch (i) { +            case 0: +                tm->tm_year = n < 50 ? n + 100 : n; +                break; +            case 1: +                tm->tm_mon = n - 1; +                break; +            case 2: +                tm->tm_mday = n; +                break; +            case 3: +                tm->tm_hour = n; +                break; +            case 4: +                tm->tm_min = n; +                break; +            case 5: +                tm->tm_sec = n; +                break; +            } +        } +    } +    if (a[o] == 'Z') +        o++; +    else if ((a[o] == '+') || (a[o] == '-')) { +        int offsign = a[o] == '-' ? 1 : -1, offset = 0; +        o++; +        if (o + 4 > l) +            goto err; +        for (i = 6; i < 8; i++) { +            if ((a[o] < '0') || (a[o] > '9')) +                goto err; +            n = a[o] - '0'; +            o++; +            if ((a[o] < '0') || (a[o] > '9')) +                goto err; +            n = (n * 10) + a[o] - '0'; +            if ((n < min[i]) || (n > max[i])) +                goto err; +            if (tm) { +                if (i == 6) +                    offset = n * 3600; +                else if (i == 7) +                    offset += n * 60; +            } +            o++; +        } +        if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign)) +            return 0; +    } +    return o == l; + err: +    return 0; +} + +int ASN1_UTCTIME_check(const ASN1_UTCTIME *d) +{ +    return asn1_utctime_to_tm(NULL, d); +} + +int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str) +{ +    ASN1_UTCTIME t; + +    t.type = V_ASN1_UTCTIME; +    t.length = strlen(str); +    t.data = (unsigned char *)str; +    if (ASN1_UTCTIME_check(&t)) { +        if (s != NULL) { +            if (!ASN1_STRING_set((ASN1_STRING *)s, str, t.length)) +                return 0; +            s->type = V_ASN1_UTCTIME; +        } +        return (1); +    } else +        return (0); +} + +ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t) +{ +    return ASN1_UTCTIME_adj(s, t, 0, 0); +} + +ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t, +                               int offset_day, long offset_sec) +{ +    char *p; +    struct tm *ts; +    struct tm data; +    size_t len = 20; +    int free_s = 0; + +    if (s == NULL) { +        s = ASN1_UTCTIME_new(); +        if (s == NULL) +            goto err; +        free_s = 1; +    } + +    ts = OPENSSL_gmtime(&t, &data); +    if (ts == NULL) +        goto err; + +    if (offset_day || offset_sec) { +        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec)) +            goto err; +    } + +    if ((ts->tm_year < 50) || (ts->tm_year >= 150)) +        goto err; + +    p = (char *)s->data; +    if ((p == NULL) || ((size_t)s->length < len)) { +        p = OPENSSL_malloc(len); +        if (p == NULL) { +            ASN1err(ASN1_F_ASN1_UTCTIME_ADJ, ERR_R_MALLOC_FAILURE); +            goto err; +        } +        OPENSSL_free(s->data); +        s->data = (unsigned char *)p; +    } + +    BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100, +                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min, +                 ts->tm_sec); +    s->length = strlen(p); +    s->type = V_ASN1_UTCTIME; +#ifdef CHARSET_EBCDIC_not +    ebcdic2ascii(s->data, s->data, s->length); +#endif +    return (s); + err: +    if (free_s) +        ASN1_UTCTIME_free(s); +    return NULL; +} + +int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t) +{ +    struct tm stm, ttm; +    int day, sec; + +    if (!asn1_utctime_to_tm(&stm, s)) +        return -2; + +    if (!OPENSSL_gmtime(&t, &ttm)) +        return -2; + +    if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm)) +        return -2; + +    if (day > 0) +        return 1; +    if (day < 0) +        return -1; +    if (sec > 0) +        return 1; +    if (sec < 0) +        return -1; +    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", +                   _asn1_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); +} diff --git a/openssl-1.1.0h/crypto/asn1/a_utf8.c b/openssl-1.1.0h/crypto/asn1/a_utf8.c new file mode 100644 index 0000000..e2dc09f --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_utf8.c @@ -0,0 +1,188 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +/* UTF8 utilities */ + +/*- + * This parses a UTF8 string one character at a time. It is passed a pointer + * to the string and the length of the string. It sets 'value' to the value of + * the current character. It returns the number of characters read or a + * negative error code: + * -1 = string too short + * -2 = illegal character + * -3 = subsequent characters not of the form 10xxxxxx + * -4 = character encoded incorrectly (not minimal length). + */ + +int UTF8_getc(const unsigned char *str, int len, unsigned long *val) +{ +    const unsigned char *p; +    unsigned long value; +    int ret; +    if (len <= 0) +        return 0; +    p = str; + +    /* Check syntax and work out the encoded value (if correct) */ +    if ((*p & 0x80) == 0) { +        value = *p++ & 0x7f; +        ret = 1; +    } else if ((*p & 0xe0) == 0xc0) { +        if (len < 2) +            return -1; +        if ((p[1] & 0xc0) != 0x80) +            return -3; +        value = (*p++ & 0x1f) << 6; +        value |= *p++ & 0x3f; +        if (value < 0x80) +            return -4; +        ret = 2; +    } else if ((*p & 0xf0) == 0xe0) { +        if (len < 3) +            return -1; +        if (((p[1] & 0xc0) != 0x80) +            || ((p[2] & 0xc0) != 0x80)) +            return -3; +        value = (*p++ & 0xf) << 12; +        value |= (*p++ & 0x3f) << 6; +        value |= *p++ & 0x3f; +        if (value < 0x800) +            return -4; +        ret = 3; +    } else if ((*p & 0xf8) == 0xf0) { +        if (len < 4) +            return -1; +        if (((p[1] & 0xc0) != 0x80) +            || ((p[2] & 0xc0) != 0x80) +            || ((p[3] & 0xc0) != 0x80)) +            return -3; +        value = ((unsigned long)(*p++ & 0x7)) << 18; +        value |= (*p++ & 0x3f) << 12; +        value |= (*p++ & 0x3f) << 6; +        value |= *p++ & 0x3f; +        if (value < 0x10000) +            return -4; +        ret = 4; +    } else if ((*p & 0xfc) == 0xf8) { +        if (len < 5) +            return -1; +        if (((p[1] & 0xc0) != 0x80) +            || ((p[2] & 0xc0) != 0x80) +            || ((p[3] & 0xc0) != 0x80) +            || ((p[4] & 0xc0) != 0x80)) +            return -3; +        value = ((unsigned long)(*p++ & 0x3)) << 24; +        value |= ((unsigned long)(*p++ & 0x3f)) << 18; +        value |= ((unsigned long)(*p++ & 0x3f)) << 12; +        value |= (*p++ & 0x3f) << 6; +        value |= *p++ & 0x3f; +        if (value < 0x200000) +            return -4; +        ret = 5; +    } else if ((*p & 0xfe) == 0xfc) { +        if (len < 6) +            return -1; +        if (((p[1] & 0xc0) != 0x80) +            || ((p[2] & 0xc0) != 0x80) +            || ((p[3] & 0xc0) != 0x80) +            || ((p[4] & 0xc0) != 0x80) +            || ((p[5] & 0xc0) != 0x80)) +            return -3; +        value = ((unsigned long)(*p++ & 0x1)) << 30; +        value |= ((unsigned long)(*p++ & 0x3f)) << 24; +        value |= ((unsigned long)(*p++ & 0x3f)) << 18; +        value |= ((unsigned long)(*p++ & 0x3f)) << 12; +        value |= (*p++ & 0x3f) << 6; +        value |= *p++ & 0x3f; +        if (value < 0x4000000) +            return -4; +        ret = 6; +    } else +        return -2; +    *val = value; +    return ret; +} + +/* + * This takes a character 'value' and writes the UTF8 encoded value in 'str' + * where 'str' is a buffer containing 'len' characters. Returns the number of + * characters written or -1 if 'len' is too small. 'str' can be set to NULL + * in which case it just returns the number of characters. It will need at + * most 6 characters. + */ + +int UTF8_putc(unsigned char *str, int len, unsigned long value) +{ +    if (!str) +        len = 6;                /* Maximum we will need */ +    else if (len <= 0) +        return -1; +    if (value < 0x80) { +        if (str) +            *str = (unsigned char)value; +        return 1; +    } +    if (value < 0x800) { +        if (len < 2) +            return -1; +        if (str) { +            *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0); +            *str = (unsigned char)((value & 0x3f) | 0x80); +        } +        return 2; +    } +    if (value < 0x10000) { +        if (len < 3) +            return -1; +        if (str) { +            *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0); +            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); +            *str = (unsigned char)((value & 0x3f) | 0x80); +        } +        return 3; +    } +    if (value < 0x200000) { +        if (len < 4) +            return -1; +        if (str) { +            *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0); +            *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); +            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); +            *str = (unsigned char)((value & 0x3f) | 0x80); +        } +        return 4; +    } +    if (value < 0x4000000) { +        if (len < 5) +            return -1; +        if (str) { +            *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8); +            *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); +            *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); +            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); +            *str = (unsigned char)((value & 0x3f) | 0x80); +        } +        return 5; +    } +    if (len < 6) +        return -1; +    if (str) { +        *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc); +        *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80); +        *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80); +        *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80); +        *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80); +        *str = (unsigned char)((value & 0x3f) | 0x80); +    } +    return 6; +} diff --git a/openssl-1.1.0h/crypto/asn1/a_verify.c b/openssl-1.1.0h/crypto/asn1/a_verify.c new file mode 100644 index 0000000..fb3607c --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/a_verify.c @@ -0,0 +1,179 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> + +#include "internal/cryptlib.h" + +#include <openssl/bn.h> +#include <openssl/x509.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/evp.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +#ifndef NO_ASN1_OLD + +int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature, +                char *data, EVP_PKEY *pkey) +{ +    EVP_MD_CTX *ctx = EVP_MD_CTX_new(); +    const EVP_MD *type; +    unsigned char *p, *buf_in = NULL; +    int ret = -1, i, inl; + +    if (ctx == NULL) { +        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    i = OBJ_obj2nid(a->algorithm); +    type = EVP_get_digestbyname(OBJ_nid2sn(i)); +    if (type == NULL) { +        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); +        goto err; +    } + +    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { +        ASN1err(ASN1_F_ASN1_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); +        goto err; +    } + +    inl = i2d(data, NULL); +    buf_in = OPENSSL_malloc((unsigned int)inl); +    if (buf_in == NULL) { +        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    p = buf_in; + +    i2d(data, &p); +    ret = EVP_VerifyInit_ex(ctx, type, NULL) +        && EVP_VerifyUpdate(ctx, (unsigned char *)buf_in, inl); + +    OPENSSL_clear_free(buf_in, (unsigned int)inl); + +    if (!ret) { +        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); +        goto err; +    } +    ret = -1; + +    if (EVP_VerifyFinal(ctx, (unsigned char *)signature->data, +                        (unsigned int)signature->length, pkey) <= 0) { +        ASN1err(ASN1_F_ASN1_VERIFY, ERR_R_EVP_LIB); +        ret = 0; +        goto err; +    } +    ret = 1; + err: +    EVP_MD_CTX_free(ctx); +    return (ret); +} + +#endif + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, +                     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) +{ +    EVP_MD_CTX *ctx = NULL; +    unsigned char *buf_in = NULL; +    int ret = -1, inl; + +    int mdnid, pknid; + +    if (!pkey) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); +        return -1; +    } + +    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_INVALID_BIT_STRING_BITS_LEFT); +        return -1; +    } + +    ctx = EVP_MD_CTX_new(); +    if (ctx == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    /* Convert signature OID into digest and public key OIDs */ +    if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); +        goto err; +    } +    if (mdnid == NID_undef) { +        if (!pkey->ameth || !pkey->ameth->item_verify) { +            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, +                    ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); +            goto err; +        } +        ret = pkey->ameth->item_verify(ctx, it, asn, a, signature, pkey); +        /* +         * Return value of 2 means carry on, anything else means we exit +         * straight away: either a fatal error of the underlying verification +         * routine handles all verification. +         */ +        if (ret != 2) +            goto err; +        ret = -1; +    } else { +        const EVP_MD *type; +        type = EVP_get_digestbynid(mdnid); +        if (type == NULL) { +            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, +                    ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); +            goto err; +        } + +        /* Check public key OID matches public key type */ +        if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { +            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ASN1_R_WRONG_PUBLIC_KEY_TYPE); +            goto err; +        } + +        if (!EVP_DigestVerifyInit(ctx, NULL, type, NULL, pkey)) { +            ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); +            ret = 0; +            goto err; +        } + +    } + +    inl = ASN1_item_i2d(asn, &buf_in, it); + +    if (buf_in == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    ret = EVP_DigestVerifyUpdate(ctx, buf_in, inl); + +    OPENSSL_clear_free(buf_in, (unsigned int)inl); + +    if (!ret) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); +        goto err; +    } +    ret = -1; + +    if (EVP_DigestVerifyFinal(ctx, signature->data, +                              (size_t)signature->length) <= 0) { +        ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_EVP_LIB); +        ret = 0; +        goto err; +    } +    ret = 1; + err: +    EVP_MD_CTX_free(ctx); +    return (ret); +} diff --git a/openssl-1.1.0h/crypto/asn1/ameth_lib.c b/openssl-1.1.0h/crypto/asn1/ameth_lib.c new file mode 100644 index 0000000..b8ba067 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/ameth_lib.c @@ -0,0 +1,411 @@ +/* + * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/engine.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +/* Keep this sorted in type order !! */ +static const EVP_PKEY_ASN1_METHOD *standard_methods[] = { +#ifndef OPENSSL_NO_RSA +    &rsa_asn1_meths[0], +    &rsa_asn1_meths[1], +#endif +#ifndef OPENSSL_NO_DH +    &dh_asn1_meth, +#endif +#ifndef OPENSSL_NO_DSA +    &dsa_asn1_meths[0], +    &dsa_asn1_meths[1], +    &dsa_asn1_meths[2], +    &dsa_asn1_meths[3], +    &dsa_asn1_meths[4], +#endif +#ifndef OPENSSL_NO_EC +    &eckey_asn1_meth, +#endif +    &hmac_asn1_meth, +#ifndef OPENSSL_NO_CMAC +    &cmac_asn1_meth, +#endif +#ifndef OPENSSL_NO_DH +    &dhx_asn1_meth, +#endif +#ifndef OPENSSL_NO_EC +    &ecx25519_asn1_meth +#endif +}; + +typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); +static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL; + +#ifdef TEST +void main() +{ +    int i; +    for (i = 0; i < OSSL_NELEM(standard_methods); i++) +        fprintf(stderr, "Number %d id=%d (%s)\n", i, +                standard_methods[i]->pkey_id, +                OBJ_nid2sn(standard_methods[i]->pkey_id)); +} +#endif + +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, +                           const EVP_PKEY_ASN1_METHOD *, ameth); + +static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a, +                     const EVP_PKEY_ASN1_METHOD *const *b) +{ +    return ((*a)->pkey_id - (*b)->pkey_id); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *, +                             const EVP_PKEY_ASN1_METHOD *, ameth); + +int EVP_PKEY_asn1_get_count(void) +{ +    int num = OSSL_NELEM(standard_methods); +    if (app_methods) +        num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods); +    return num; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx) +{ +    int num = OSSL_NELEM(standard_methods); +    if (idx < 0) +        return NULL; +    if (idx < num) +        return standard_methods[idx]; +    idx -= num; +    return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); +} + +static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type) +{ +    EVP_PKEY_ASN1_METHOD tmp; +    const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret; +    tmp.pkey_id = type; +    if (app_methods) { +        int idx; +        idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp); +        if (idx >= 0) +            return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx); +    } +    ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods)); +    if (!ret || !*ret) +        return NULL; +    return *ret; +} + +/* + * Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also + * search through engines and set *pe to a functional reference to the engine + * implementing 'type' or NULL if no engine implements it. + */ + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type) +{ +    const EVP_PKEY_ASN1_METHOD *t; + +    for (;;) { +        t = pkey_asn1_find(type); +        if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS)) +            break; +        type = t->pkey_base_id; +    } +    if (pe) { +#ifndef OPENSSL_NO_ENGINE +        ENGINE *e; +        /* type will contain the final unaliased type */ +        e = ENGINE_get_pkey_asn1_meth_engine(type); +        if (e) { +            *pe = e; +            return ENGINE_get_pkey_asn1_meth(e, type); +        } +#endif +        *pe = NULL; +    } +    return t; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe, +                                                   const char *str, int len) +{ +    int i; +    const EVP_PKEY_ASN1_METHOD *ameth = NULL; + +    if (len == -1) +        len = strlen(str); +    if (pe) { +#ifndef OPENSSL_NO_ENGINE +        ENGINE *e; +        ameth = ENGINE_pkey_asn1_find_str(&e, str, len); +        if (ameth) { +            /* +             * Convert structural into functional reference +             */ +            if (!ENGINE_init(e)) +                ameth = NULL; +            ENGINE_free(e); +            *pe = e; +            return ameth; +        } +#endif +        *pe = NULL; +    } +    for (i = EVP_PKEY_asn1_get_count(); i-- > 0; ) { +        ameth = EVP_PKEY_asn1_get0(i); +        if (ameth->pkey_flags & ASN1_PKEY_ALIAS) +            continue; +        if ((int)strlen(ameth->pem_str) == len +            && strncasecmp(ameth->pem_str, str, len) == 0) +            return ameth; +    } +    return NULL; +} + +int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth) +{ +    EVP_PKEY_ASN1_METHOD tmp = { 0, }; + +    if (app_methods == NULL) { +        app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp); +        if (app_methods == NULL) +            return 0; +    } + +    tmp.pkey_id = ameth->pkey_id; +    if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) { +        EVPerr(EVP_F_EVP_PKEY_ASN1_ADD0, +               EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED); +        return 0; +    } + +    if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth)) +        return 0; +    sk_EVP_PKEY_ASN1_METHOD_sort(app_methods); +    return 1; +} + +int EVP_PKEY_asn1_add_alias(int to, int from) +{ +    EVP_PKEY_ASN1_METHOD *ameth; +    ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL); +    if (ameth == NULL) +        return 0; +    ameth->pkey_base_id = to; +    if (!EVP_PKEY_asn1_add0(ameth)) { +        EVP_PKEY_asn1_free(ameth); +        return 0; +    } +    return 1; +} + +int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, +                            int *ppkey_flags, const char **pinfo, +                            const char **ppem_str, +                            const EVP_PKEY_ASN1_METHOD *ameth) +{ +    if (!ameth) +        return 0; +    if (ppkey_id) +        *ppkey_id = ameth->pkey_id; +    if (ppkey_base_id) +        *ppkey_base_id = ameth->pkey_base_id; +    if (ppkey_flags) +        *ppkey_flags = ameth->pkey_flags; +    if (pinfo) +        *pinfo = ameth->info; +    if (ppem_str) +        *ppem_str = ameth->pem_str; +    return 1; +} + +const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey) +{ +    return pkey->ameth; +} + +EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags, +                                        const char *pem_str, const char *info) +{ +    EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth)); + +    if (ameth == NULL) +        return NULL; + +    ameth->pkey_id = id; +    ameth->pkey_base_id = id; +    ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC; + +    if (info) { +        ameth->info = OPENSSL_strdup(info); +        if (!ameth->info) +            goto err; +    } + +    if (pem_str) { +        ameth->pem_str = OPENSSL_strdup(pem_str); +        if (!ameth->pem_str) +            goto err; +    } + +    return ameth; + + err: +    EVP_PKEY_asn1_free(ameth); +    return NULL; + +} + +void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, +                        const EVP_PKEY_ASN1_METHOD *src) +{ + +    dst->pub_decode = src->pub_decode; +    dst->pub_encode = src->pub_encode; +    dst->pub_cmp = src->pub_cmp; +    dst->pub_print = src->pub_print; + +    dst->priv_decode = src->priv_decode; +    dst->priv_encode = src->priv_encode; +    dst->priv_print = src->priv_print; + +    dst->old_priv_encode = src->old_priv_encode; +    dst->old_priv_decode = src->old_priv_decode; + +    dst->pkey_size = src->pkey_size; +    dst->pkey_bits = src->pkey_bits; + +    dst->param_decode = src->param_decode; +    dst->param_encode = src->param_encode; +    dst->param_missing = src->param_missing; +    dst->param_copy = src->param_copy; +    dst->param_cmp = src->param_cmp; +    dst->param_print = src->param_print; + +    dst->pkey_free = src->pkey_free; +    dst->pkey_ctrl = src->pkey_ctrl; + +    dst->item_sign = src->item_sign; +    dst->item_verify = src->item_verify; + +} + +void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth) +{ +    if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) { +        OPENSSL_free(ameth->pem_str); +        OPENSSL_free(ameth->info); +        OPENSSL_free(ameth); +    } +} + +void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth, +                              int (*pub_decode) (EVP_PKEY *pk, +                                                 X509_PUBKEY *pub), +                              int (*pub_encode) (X509_PUBKEY *pub, +                                                 const EVP_PKEY *pk), +                              int (*pub_cmp) (const EVP_PKEY *a, +                                              const EVP_PKEY *b), +                              int (*pub_print) (BIO *out, +                                                const EVP_PKEY *pkey, +                                                int indent, ASN1_PCTX *pctx), +                              int (*pkey_size) (const EVP_PKEY *pk), +                              int (*pkey_bits) (const EVP_PKEY *pk)) +{ +    ameth->pub_decode = pub_decode; +    ameth->pub_encode = pub_encode; +    ameth->pub_cmp = pub_cmp; +    ameth->pub_print = pub_print; +    ameth->pkey_size = pkey_size; +    ameth->pkey_bits = pkey_bits; +} + +void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth, +                               int (*priv_decode) (EVP_PKEY *pk, +                                                   const PKCS8_PRIV_KEY_INFO +                                                   *p8inf), +                               int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8, +                                                   const EVP_PKEY *pk), +                               int (*priv_print) (BIO *out, +                                                  const EVP_PKEY *pkey, +                                                  int indent, +                                                  ASN1_PCTX *pctx)) +{ +    ameth->priv_decode = priv_decode; +    ameth->priv_encode = priv_encode; +    ameth->priv_print = priv_print; +} + +void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth, +                             int (*param_decode) (EVP_PKEY *pkey, +                                                  const unsigned char **pder, +                                                  int derlen), +                             int (*param_encode) (const EVP_PKEY *pkey, +                                                  unsigned char **pder), +                             int (*param_missing) (const EVP_PKEY *pk), +                             int (*param_copy) (EVP_PKEY *to, +                                                const EVP_PKEY *from), +                             int (*param_cmp) (const EVP_PKEY *a, +                                               const EVP_PKEY *b), +                             int (*param_print) (BIO *out, +                                                 const EVP_PKEY *pkey, +                                                 int indent, ASN1_PCTX *pctx)) +{ +    ameth->param_decode = param_decode; +    ameth->param_encode = param_encode; +    ameth->param_missing = param_missing; +    ameth->param_copy = param_copy; +    ameth->param_cmp = param_cmp; +    ameth->param_print = param_print; +} + +void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth, +                            void (*pkey_free) (EVP_PKEY *pkey)) +{ +    ameth->pkey_free = pkey_free; +} + +void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth, +                            int (*pkey_ctrl) (EVP_PKEY *pkey, int op, +                                              long arg1, void *arg2)) +{ +    ameth->pkey_ctrl = pkey_ctrl; +} + +void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth, +                                     int (*pkey_security_bits) (const EVP_PKEY +                                                                *pk)) +{ +    ameth->pkey_security_bits = pkey_security_bits; +} + +void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth, +                            int (*item_verify) (EVP_MD_CTX *ctx, +                                                const ASN1_ITEM *it, +                                                void *asn, +                                                X509_ALGOR *a, +                                                ASN1_BIT_STRING *sig, +                                                EVP_PKEY *pkey), +                            int (*item_sign) (EVP_MD_CTX *ctx, +                                              const ASN1_ITEM *it, +                                              void *asn, +                                              X509_ALGOR *alg1, +                                              X509_ALGOR *alg2, +                                              ASN1_BIT_STRING *sig)) +{ +    ameth->item_sign = item_sign; +    ameth->item_verify = item_verify; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn1_err.c b/openssl-1.1.0h/crypto/asn1/asn1_err.c new file mode 100644 index 0000000..8602c40 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn1_err.c @@ -0,0 +1,271 @@ +/* + * Generated by util/mkerr.pl DO NOT EDIT + * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <openssl/err.h> +#include <openssl/asn1.h> + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_ASN1,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_ASN1,0,reason) + +static ERR_STRING_DATA ASN1_str_functs[] = { +    {ERR_FUNC(ASN1_F_A2D_ASN1_OBJECT), "a2d_ASN1_OBJECT"}, +    {ERR_FUNC(ASN1_F_A2I_ASN1_INTEGER), "a2i_ASN1_INTEGER"}, +    {ERR_FUNC(ASN1_F_A2I_ASN1_STRING), "a2i_ASN1_STRING"}, +    {ERR_FUNC(ASN1_F_APPEND_EXP), "append_exp"}, +    {ERR_FUNC(ASN1_F_ASN1_BIT_STRING_SET_BIT), "ASN1_BIT_STRING_set_bit"}, +    {ERR_FUNC(ASN1_F_ASN1_CB), "asn1_cb"}, +    {ERR_FUNC(ASN1_F_ASN1_CHECK_TLEN), "asn1_check_tlen"}, +    {ERR_FUNC(ASN1_F_ASN1_COLLECT), "asn1_collect"}, +    {ERR_FUNC(ASN1_F_ASN1_D2I_EX_PRIMITIVE), "asn1_d2i_ex_primitive"}, +    {ERR_FUNC(ASN1_F_ASN1_D2I_FP), "ASN1_d2i_fp"}, +    {ERR_FUNC(ASN1_F_ASN1_D2I_READ_BIO), "asn1_d2i_read_bio"}, +    {ERR_FUNC(ASN1_F_ASN1_DIGEST), "ASN1_digest"}, +    {ERR_FUNC(ASN1_F_ASN1_DO_ADB), "asn1_do_adb"}, +    {ERR_FUNC(ASN1_F_ASN1_DO_LOCK), "asn1_do_lock"}, +    {ERR_FUNC(ASN1_F_ASN1_DUP), "ASN1_dup"}, +    {ERR_FUNC(ASN1_F_ASN1_EX_C2I), "asn1_ex_c2i"}, +    {ERR_FUNC(ASN1_F_ASN1_FIND_END), "asn1_find_end"}, +    {ERR_FUNC(ASN1_F_ASN1_GENERALIZEDTIME_ADJ), "ASN1_GENERALIZEDTIME_adj"}, +    {ERR_FUNC(ASN1_F_ASN1_GENERATE_V3), "ASN1_generate_v3"}, +    {ERR_FUNC(ASN1_F_ASN1_GET_INT64), "asn1_get_int64"}, +    {ERR_FUNC(ASN1_F_ASN1_GET_OBJECT), "ASN1_get_object"}, +    {ERR_FUNC(ASN1_F_ASN1_GET_UINT64), "asn1_get_uint64"}, +    {ERR_FUNC(ASN1_F_ASN1_I2D_BIO), "ASN1_i2d_bio"}, +    {ERR_FUNC(ASN1_F_ASN1_I2D_FP), "ASN1_i2d_fp"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_D2I_FP), "ASN1_item_d2i_fp"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_DUP), "ASN1_item_dup"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_EMBED_D2I), "asn1_item_embed_d2i"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_EMBED_NEW), "asn1_item_embed_new"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_BIO), "ASN1_item_i2d_bio"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_I2D_FP), "ASN1_item_i2d_fp"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_PACK), "ASN1_item_pack"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN), "ASN1_item_sign"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_SIGN_CTX), "ASN1_item_sign_ctx"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_UNPACK), "ASN1_item_unpack"}, +    {ERR_FUNC(ASN1_F_ASN1_ITEM_VERIFY), "ASN1_item_verify"}, +    {ERR_FUNC(ASN1_F_ASN1_MBSTRING_NCOPY), "ASN1_mbstring_ncopy"}, +    {ERR_FUNC(ASN1_F_ASN1_OBJECT_NEW), "ASN1_OBJECT_new"}, +    {ERR_FUNC(ASN1_F_ASN1_OUTPUT_DATA), "asn1_output_data"}, +    {ERR_FUNC(ASN1_F_ASN1_PCTX_NEW), "ASN1_PCTX_new"}, +    {ERR_FUNC(ASN1_F_ASN1_SCTX_NEW), "ASN1_SCTX_new"}, +    {ERR_FUNC(ASN1_F_ASN1_SIGN), "ASN1_sign"}, +    {ERR_FUNC(ASN1_F_ASN1_STR2TYPE), "asn1_str2type"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_GET_INT64), "asn1_string_get_int64"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_GET_UINT64), "asn1_string_get_uint64"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_SET), "ASN1_STRING_set"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_TABLE_ADD), "ASN1_STRING_TABLE_add"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_TO_BN), "asn1_string_to_bn"}, +    {ERR_FUNC(ASN1_F_ASN1_STRING_TYPE_NEW), "ASN1_STRING_type_new"}, +    {ERR_FUNC(ASN1_F_ASN1_TEMPLATE_EX_D2I), "asn1_template_ex_d2i"}, +    {ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NEW), "asn1_template_new"}, +    {ERR_FUNC(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I), "asn1_template_noexp_d2i"}, +    {ERR_FUNC(ASN1_F_ASN1_TIME_ADJ), "ASN1_TIME_adj"}, +    {ERR_FUNC(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING), +     "ASN1_TYPE_get_int_octetstring"}, +    {ERR_FUNC(ASN1_F_ASN1_TYPE_GET_OCTETSTRING), "ASN1_TYPE_get_octetstring"}, +    {ERR_FUNC(ASN1_F_ASN1_UTCTIME_ADJ), "ASN1_UTCTIME_adj"}, +    {ERR_FUNC(ASN1_F_ASN1_VERIFY), "ASN1_verify"}, +    {ERR_FUNC(ASN1_F_B64_READ_ASN1), "b64_read_asn1"}, +    {ERR_FUNC(ASN1_F_B64_WRITE_ASN1), "B64_write_ASN1"}, +    {ERR_FUNC(ASN1_F_BIO_NEW_NDEF), "BIO_new_NDEF"}, +    {ERR_FUNC(ASN1_F_BITSTR_CB), "bitstr_cb"}, +    {ERR_FUNC(ASN1_F_BN_TO_ASN1_STRING), "bn_to_asn1_string"}, +    {ERR_FUNC(ASN1_F_C2I_ASN1_BIT_STRING), "c2i_ASN1_BIT_STRING"}, +    {ERR_FUNC(ASN1_F_C2I_ASN1_INTEGER), "c2i_ASN1_INTEGER"}, +    {ERR_FUNC(ASN1_F_C2I_ASN1_OBJECT), "c2i_ASN1_OBJECT"}, +    {ERR_FUNC(ASN1_F_C2I_IBUF), "c2i_ibuf"}, +    {ERR_FUNC(ASN1_F_C2I_UINT64_INT), "c2i_uint64_int"}, +    {ERR_FUNC(ASN1_F_COLLECT_DATA), "collect_data"}, +    {ERR_FUNC(ASN1_F_D2I_ASN1_OBJECT), "d2i_ASN1_OBJECT"}, +    {ERR_FUNC(ASN1_F_D2I_ASN1_UINTEGER), "d2i_ASN1_UINTEGER"}, +    {ERR_FUNC(ASN1_F_D2I_AUTOPRIVATEKEY), "d2i_AutoPrivateKey"}, +    {ERR_FUNC(ASN1_F_D2I_PRIVATEKEY), "d2i_PrivateKey"}, +    {ERR_FUNC(ASN1_F_D2I_PUBLICKEY), "d2i_PublicKey"}, +    {ERR_FUNC(ASN1_F_DO_TCREATE), "do_tcreate"}, +    {ERR_FUNC(ASN1_F_I2D_ASN1_BIO_STREAM), "i2d_ASN1_bio_stream"}, +    {ERR_FUNC(ASN1_F_I2D_DSA_PUBKEY), "i2d_DSA_PUBKEY"}, +    {ERR_FUNC(ASN1_F_I2D_EC_PUBKEY), "i2d_EC_PUBKEY"}, +    {ERR_FUNC(ASN1_F_I2D_PRIVATEKEY), "i2d_PrivateKey"}, +    {ERR_FUNC(ASN1_F_I2D_PUBLICKEY), "i2d_PublicKey"}, +    {ERR_FUNC(ASN1_F_I2D_RSA_PUBKEY), "i2d_RSA_PUBKEY"}, +    {ERR_FUNC(ASN1_F_LONG_C2I), "long_c2i"}, +    {ERR_FUNC(ASN1_F_OID_MODULE_INIT), "oid_module_init"}, +    {ERR_FUNC(ASN1_F_PARSE_TAGGING), "parse_tagging"}, +    {ERR_FUNC(ASN1_F_PKCS5_PBE2_SET_IV), "PKCS5_pbe2_set_iv"}, +    {ERR_FUNC(ASN1_F_PKCS5_PBE2_SET_SCRYPT), "PKCS5_pbe2_set_scrypt"}, +    {ERR_FUNC(ASN1_F_PKCS5_PBE_SET), "PKCS5_pbe_set"}, +    {ERR_FUNC(ASN1_F_PKCS5_PBE_SET0_ALGOR), "PKCS5_pbe_set0_algor"}, +    {ERR_FUNC(ASN1_F_PKCS5_PBKDF2_SET), "PKCS5_pbkdf2_set"}, +    {ERR_FUNC(ASN1_F_PKCS5_SCRYPT_SET), "pkcs5_scrypt_set"}, +    {ERR_FUNC(ASN1_F_SMIME_READ_ASN1), "SMIME_read_ASN1"}, +    {ERR_FUNC(ASN1_F_SMIME_TEXT), "SMIME_text"}, +    {ERR_FUNC(ASN1_F_STBL_MODULE_INIT), "stbl_module_init"}, +    {ERR_FUNC(ASN1_F_UINT32_C2I), "uint32_c2i"}, +    {ERR_FUNC(ASN1_F_UINT64_C2I), "uint64_c2i"}, +    {ERR_FUNC(ASN1_F_X509_CRL_ADD0_REVOKED), "X509_CRL_add0_revoked"}, +    {ERR_FUNC(ASN1_F_X509_INFO_NEW), "X509_INFO_new"}, +    {ERR_FUNC(ASN1_F_X509_NAME_ENCODE), "x509_name_encode"}, +    {ERR_FUNC(ASN1_F_X509_NAME_EX_D2I), "x509_name_ex_d2i"}, +    {ERR_FUNC(ASN1_F_X509_NAME_EX_NEW), "x509_name_ex_new"}, +    {ERR_FUNC(ASN1_F_X509_PKEY_NEW), "X509_PKEY_new"}, +    {0, NULL} +}; + +static ERR_STRING_DATA ASN1_str_reasons[] = { +    {ERR_REASON(ASN1_R_ADDING_OBJECT), "adding object"}, +    {ERR_REASON(ASN1_R_ASN1_PARSE_ERROR), "asn1 parse error"}, +    {ERR_REASON(ASN1_R_ASN1_SIG_PARSE_ERROR), "asn1 sig parse error"}, +    {ERR_REASON(ASN1_R_AUX_ERROR), "aux error"}, +    {ERR_REASON(ASN1_R_BAD_OBJECT_HEADER), "bad object header"}, +    {ERR_REASON(ASN1_R_BMPSTRING_IS_WRONG_LENGTH), +     "bmpstring is wrong length"}, +    {ERR_REASON(ASN1_R_BN_LIB), "bn lib"}, +    {ERR_REASON(ASN1_R_BOOLEAN_IS_WRONG_LENGTH), "boolean is wrong length"}, +    {ERR_REASON(ASN1_R_BUFFER_TOO_SMALL), "buffer too small"}, +    {ERR_REASON(ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER), +     "cipher has no object identifier"}, +    {ERR_REASON(ASN1_R_CONTEXT_NOT_INITIALISED), "context not initialised"}, +    {ERR_REASON(ASN1_R_DATA_IS_WRONG), "data is wrong"}, +    {ERR_REASON(ASN1_R_DECODE_ERROR), "decode error"}, +    {ERR_REASON(ASN1_R_DEPTH_EXCEEDED), "depth exceeded"}, +    {ERR_REASON(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED), +     "digest and key type not supported"}, +    {ERR_REASON(ASN1_R_ENCODE_ERROR), "encode error"}, +    {ERR_REASON(ASN1_R_ERROR_GETTING_TIME), "error getting time"}, +    {ERR_REASON(ASN1_R_ERROR_LOADING_SECTION), "error loading section"}, +    {ERR_REASON(ASN1_R_ERROR_SETTING_CIPHER_PARAMS), +     "error setting cipher params"}, +    {ERR_REASON(ASN1_R_EXPECTING_AN_INTEGER), "expecting an integer"}, +    {ERR_REASON(ASN1_R_EXPECTING_AN_OBJECT), "expecting an object"}, +    {ERR_REASON(ASN1_R_EXPLICIT_LENGTH_MISMATCH), "explicit length mismatch"}, +    {ERR_REASON(ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED), +     "explicit tag not constructed"}, +    {ERR_REASON(ASN1_R_FIELD_MISSING), "field missing"}, +    {ERR_REASON(ASN1_R_FIRST_NUM_TOO_LARGE), "first num too large"}, +    {ERR_REASON(ASN1_R_HEADER_TOO_LONG), "header too long"}, +    {ERR_REASON(ASN1_R_ILLEGAL_BITSTRING_FORMAT), "illegal bitstring format"}, +    {ERR_REASON(ASN1_R_ILLEGAL_BOOLEAN), "illegal boolean"}, +    {ERR_REASON(ASN1_R_ILLEGAL_CHARACTERS), "illegal characters"}, +    {ERR_REASON(ASN1_R_ILLEGAL_FORMAT), "illegal format"}, +    {ERR_REASON(ASN1_R_ILLEGAL_HEX), "illegal hex"}, +    {ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG), "illegal implicit tag"}, +    {ERR_REASON(ASN1_R_ILLEGAL_INTEGER), "illegal integer"}, +    {ERR_REASON(ASN1_R_ILLEGAL_NEGATIVE_VALUE), "illegal negative value"}, +    {ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"}, +    {ERR_REASON(ASN1_R_ILLEGAL_NULL), "illegal null"}, +    {ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE), "illegal null value"}, +    {ERR_REASON(ASN1_R_ILLEGAL_OBJECT), "illegal object"}, +    {ERR_REASON(ASN1_R_ILLEGAL_OPTIONAL_ANY), "illegal optional any"}, +    {ERR_REASON(ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE), +     "illegal options on item template"}, +    {ERR_REASON(ASN1_R_ILLEGAL_PADDING), "illegal padding"}, +    {ERR_REASON(ASN1_R_ILLEGAL_TAGGED_ANY), "illegal tagged any"}, +    {ERR_REASON(ASN1_R_ILLEGAL_TIME_VALUE), "illegal time value"}, +    {ERR_REASON(ASN1_R_ILLEGAL_ZERO_CONTENT), "illegal zero content"}, +    {ERR_REASON(ASN1_R_INTEGER_NOT_ASCII_FORMAT), "integer not ascii format"}, +    {ERR_REASON(ASN1_R_INTEGER_TOO_LARGE_FOR_LONG), +     "integer too large for long"}, +    {ERR_REASON(ASN1_R_INVALID_BIT_STRING_BITS_LEFT), +     "invalid bit string bits left"}, +    {ERR_REASON(ASN1_R_INVALID_BMPSTRING_LENGTH), "invalid bmpstring length"}, +    {ERR_REASON(ASN1_R_INVALID_DIGIT), "invalid digit"}, +    {ERR_REASON(ASN1_R_INVALID_MIME_TYPE), "invalid mime type"}, +    {ERR_REASON(ASN1_R_INVALID_MODIFIER), "invalid modifier"}, +    {ERR_REASON(ASN1_R_INVALID_NUMBER), "invalid number"}, +    {ERR_REASON(ASN1_R_INVALID_OBJECT_ENCODING), "invalid object encoding"}, +    {ERR_REASON(ASN1_R_INVALID_SCRYPT_PARAMETERS), +     "invalid scrypt parameters"}, +    {ERR_REASON(ASN1_R_INVALID_SEPARATOR), "invalid separator"}, +    {ERR_REASON(ASN1_R_INVALID_STRING_TABLE_VALUE), +     "invalid string table value"}, +    {ERR_REASON(ASN1_R_INVALID_UNIVERSALSTRING_LENGTH), +     "invalid universalstring length"}, +    {ERR_REASON(ASN1_R_INVALID_UTF8STRING), "invalid utf8string"}, +    {ERR_REASON(ASN1_R_INVALID_VALUE), "invalid value"}, +    {ERR_REASON(ASN1_R_LIST_ERROR), "list error"}, +    {ERR_REASON(ASN1_R_MIME_NO_CONTENT_TYPE), "mime no content type"}, +    {ERR_REASON(ASN1_R_MIME_PARSE_ERROR), "mime parse error"}, +    {ERR_REASON(ASN1_R_MIME_SIG_PARSE_ERROR), "mime sig parse error"}, +    {ERR_REASON(ASN1_R_MISSING_EOC), "missing eoc"}, +    {ERR_REASON(ASN1_R_MISSING_SECOND_NUMBER), "missing second number"}, +    {ERR_REASON(ASN1_R_MISSING_VALUE), "missing value"}, +    {ERR_REASON(ASN1_R_MSTRING_NOT_UNIVERSAL), "mstring not universal"}, +    {ERR_REASON(ASN1_R_MSTRING_WRONG_TAG), "mstring wrong tag"}, +    {ERR_REASON(ASN1_R_NESTED_ASN1_STRING), "nested asn1 string"}, +    {ERR_REASON(ASN1_R_NESTED_TOO_DEEP), "nested too deep"}, +    {ERR_REASON(ASN1_R_NON_HEX_CHARACTERS), "non hex characters"}, +    {ERR_REASON(ASN1_R_NOT_ASCII_FORMAT), "not ascii format"}, +    {ERR_REASON(ASN1_R_NOT_ENOUGH_DATA), "not enough data"}, +    {ERR_REASON(ASN1_R_NO_CONTENT_TYPE), "no content type"}, +    {ERR_REASON(ASN1_R_NO_MATCHING_CHOICE_TYPE), "no matching choice type"}, +    {ERR_REASON(ASN1_R_NO_MULTIPART_BODY_FAILURE), +     "no multipart body failure"}, +    {ERR_REASON(ASN1_R_NO_MULTIPART_BOUNDARY), "no multipart boundary"}, +    {ERR_REASON(ASN1_R_NO_SIG_CONTENT_TYPE), "no sig content type"}, +    {ERR_REASON(ASN1_R_NULL_IS_WRONG_LENGTH), "null is wrong length"}, +    {ERR_REASON(ASN1_R_OBJECT_NOT_ASCII_FORMAT), "object not ascii format"}, +    {ERR_REASON(ASN1_R_ODD_NUMBER_OF_CHARS), "odd number of chars"}, +    {ERR_REASON(ASN1_R_SECOND_NUMBER_TOO_LARGE), "second number too large"}, +    {ERR_REASON(ASN1_R_SEQUENCE_LENGTH_MISMATCH), "sequence length mismatch"}, +    {ERR_REASON(ASN1_R_SEQUENCE_NOT_CONSTRUCTED), "sequence not constructed"}, +    {ERR_REASON(ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG), +     "sequence or set needs config"}, +    {ERR_REASON(ASN1_R_SHORT_LINE), "short line"}, +    {ERR_REASON(ASN1_R_SIG_INVALID_MIME_TYPE), "sig invalid mime type"}, +    {ERR_REASON(ASN1_R_STREAMING_NOT_SUPPORTED), "streaming not supported"}, +    {ERR_REASON(ASN1_R_STRING_TOO_LONG), "string too long"}, +    {ERR_REASON(ASN1_R_STRING_TOO_SHORT), "string too short"}, +    {ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), +     "the asn1 object identifier is not known for this md"}, +    {ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"}, +    {ERR_REASON(ASN1_R_TOO_LARGE), "too large"}, +    {ERR_REASON(ASN1_R_TOO_LONG), "too long"}, +    {ERR_REASON(ASN1_R_TOO_SMALL), "too small"}, +    {ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED), "type not constructed"}, +    {ERR_REASON(ASN1_R_TYPE_NOT_PRIMITIVE), "type not primitive"}, +    {ERR_REASON(ASN1_R_UNEXPECTED_EOC), "unexpected eoc"}, +    {ERR_REASON(ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH), +     "universalstring is wrong length"}, +    {ERR_REASON(ASN1_R_UNKNOWN_FORMAT), "unknown format"}, +    {ERR_REASON(ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM), +     "unknown message digest algorithm"}, +    {ERR_REASON(ASN1_R_UNKNOWN_OBJECT_TYPE), "unknown object type"}, +    {ERR_REASON(ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE), "unknown public key type"}, +    {ERR_REASON(ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM), +     "unknown signature algorithm"}, +    {ERR_REASON(ASN1_R_UNKNOWN_TAG), "unknown tag"}, +    {ERR_REASON(ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE), +     "unsupported any defined by type"}, +    {ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), +     "unsupported public key type"}, +    {ERR_REASON(ASN1_R_UNSUPPORTED_TYPE), "unsupported type"}, +    {ERR_REASON(ASN1_R_WRONG_INTEGER_TYPE), "wrong integer type"}, +    {ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"}, +    {ERR_REASON(ASN1_R_WRONG_TAG), "wrong tag"}, +    {0, NULL} +}; + +#endif + +int ERR_load_ASN1_strings(void) +{ +#ifndef OPENSSL_NO_ERR + +    if (ERR_func_error_string(ASN1_str_functs[0].error) == NULL) { +        ERR_load_strings(0, ASN1_str_functs); +        ERR_load_strings(0, ASN1_str_reasons); +    } +#endif +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn1_gen.c b/openssl-1.1.0h/crypto/asn1/asn1_gen.c new file mode 100644 index 0000000..493a693 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn1_gen.c @@ -0,0 +1,789 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/cryptlib.h" +#include <openssl/asn1.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 +/* Maximum number of nested sequences */ +#define ASN1_GEN_SEQ_MAX_DEPTH  50 + +/* 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 ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, +                              int *perr); +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, +                             int depth, int *perr); +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(const 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(const char *str, X509V3_CTX *cnf) +{ +    int err = 0; +    ASN1_TYPE *ret = generate_v3(str, cnf, 0, &err); +    if (err) +        ASN1err(ASN1_F_ASN1_GENERATE_V3, err); +    return ret; +} + +static ASN1_TYPE *generate_v3(const char *str, X509V3_CTX *cnf, int depth, +                              int *perr) +{ +    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 = 0; +    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) { +        *perr = ASN1_R_UNKNOWN_TAG; +        return NULL; +    } + +    if ((asn1_tags.utype == V_ASN1_SEQUENCE) +        || (asn1_tags.utype == V_ASN1_SET)) { +        if (!cnf) { +            *perr = ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG; +            return NULL; +        } +        if (depth >= ASN1_GEN_SEQ_MAX_DEPTH) { +            *perr = ASN1_R_ILLEGAL_NESTED_TAGGING; +            return NULL; +        } +        ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf, depth, perr); +    } 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 == NULL) +        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: +    OPENSSL_free(orig_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 -1; + +    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) { +        ASN1err(ASN1_F_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]) { +            ASN1err(ASN1_F_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) { +            ASN1err(ASN1_F_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 (!vstart) { +            ASN1err(ASN1_F_ASN1_CB, ASN1_R_UNKNOWN_FORMAT); +            return -1; +        } +        if (strncmp(vstart, "ASCII", 5) == 0) +            arg->format = ASN1_GEN_FORMAT_ASCII; +        else if (strncmp(vstart, "UTF8", 4) == 0) +            arg->format = ASN1_GEN_FORMAT_UTF8; +        else if (strncmp(vstart, "HEX", 3) == 0) +            arg->format = ASN1_GEN_FORMAT_HEX; +        else if (strncmp(vstart, "BITLIST", 7) == 0) +            arg->format = ASN1_GEN_FORMAT_BITLIST; +        else { +            ASN1err(ASN1_F_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) { +        ASN1err(ASN1_F_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; +            ASN1err(ASN1_F_PARSE_TAGGING, ASN1_R_INVALID_MODIFIER); +            ERR_add_error_data(2, "Char=", erch); +            return 0; + +        } +    } 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, +                             int depth, int *perr) +{ +    ASN1_TYPE *ret = NULL; +    STACK_OF(ASN1_TYPE) *sk = NULL; +    STACK_OF(CONF_VALUE) *sect = NULL; +    unsigned char *der = NULL; +    int derlen; +    int 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 = +                generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf, +                            depth + 1, perr); +            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()) == NULL) +        goto bad; +    if ((ret->value.asn1_string = ASN1_STRING_type_new(utype)) == NULL) +        goto bad; + +    ret->type = utype; +    ret->value.asn1_string->data = der; +    ret->value.asn1_string->length = derlen; + +    der = NULL; + + bad: + +    OPENSSL_free(der); + +    sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); +    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) { +        ASN1err(ASN1_F_APPEND_EXP, ASN1_R_ILLEGAL_IMPLICIT_TAG); +        return 0; +    } + +    if (arg->exp_count == ASN1_FLAG_EXP_MAX) { +        ASN1err(ASN1_F_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 < OSSL_NELEM(tnst); i++, tntmp++) { +        if ((len == tntmp->len) && (strncmp(tntmp->strnam, tagstr, len) == 0)) +            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()) == NULL) { +        ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); +        return NULL; +    } + +    if (!str) +        str = ""; + +    switch (utype) { + +    case V_ASN1_NULL: +        if (str && *str) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_NULL_VALUE); +            goto bad_form; +        } +        break; + +    case V_ASN1_BOOLEAN: +        if (format != ASN1_GEN_FORMAT_ASCII) { +            ASN1err(ASN1_F_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)) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_BOOLEAN); +            goto bad_str; +        } +        break; + +    case V_ASN1_INTEGER: +    case V_ASN1_ENUMERATED: +        if (format != ASN1_GEN_FORMAT_ASCII) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_INTEGER_NOT_ASCII_FORMAT); +            goto bad_form; +        } +        if ((atmp->value.integer +                    = s2i_ASN1_INTEGER(NULL, str)) == NULL) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_INTEGER); +            goto bad_str; +        } +        break; + +    case V_ASN1_OBJECT: +        if (format != ASN1_GEN_FORMAT_ASCII) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_OBJECT_NOT_ASCII_FORMAT); +            goto bad_form; +        } +        if ((atmp->value.object = OBJ_txt2obj(str, 0)) == NULL) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_ILLEGAL_OBJECT); +            goto bad_str; +        } +        break; + +    case V_ASN1_UTCTIME: +    case V_ASN1_GENERALIZEDTIME: +        if (format != ASN1_GEN_FORMAT_ASCII) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_TIME_NOT_ASCII_FORMAT); +            goto bad_form; +        } +        if ((atmp->value.asn1_string = ASN1_STRING_new()) == NULL) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); +            goto bad_str; +        } +        if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); +            goto bad_str; +        } +        atmp->value.asn1_string->type = utype; +        if (!ASN1_TIME_check(atmp->value.asn1_string)) { +            ASN1err(ASN1_F_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 { +            ASN1err(ASN1_F_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) { +            ASN1err(ASN1_F_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()) == NULL) { +            ASN1err(ASN1_F_ASN1_STR2TYPE, ERR_R_MALLOC_FAILURE); +            goto bad_form; +        } + +        if (format == ASN1_GEN_FORMAT_HEX) { +            if ((rdata = OPENSSL_hexstr2buf(str, &rdlen)) == NULL) { +                ASN1err(ASN1_F_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)) { +                ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_LIST_ERROR); +                goto bad_str; +            } +            no_unused = 0; + +        } else { +            ASN1err(ASN1_F_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: +        ASN1err(ASN1_F_ASN1_STR2TYPE, ASN1_R_UNSUPPORTED_TYPE); +        goto bad_str; +    } + +    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) { +        ASN1err(ASN1_F_BITSTR_CB, ASN1_R_INVALID_NUMBER); +        return 0; +    } +    if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) { +        ASN1err(ASN1_F_BITSTR_CB, ERR_R_MALLOC_FAILURE); +        return 0; +    } +    return 1; +} + +static int mask_cb(const char *elem, int len, void *arg) +{ +    unsigned long *pmask = arg, tmpmask; +    int tag; +    if (elem == NULL) +        return 0; +    if ((len == 3) && (strncmp(elem, "DIR", 3) == 0)) { +        *pmask |= B_ASN1_DIRECTORYSTRING; +        return 1; +    } +    tag = asn1_str2tag(elem, len); +    if (!tag || (tag & ASN1_GEN_FLAG)) +        return 0; +    tmpmask = ASN1_tag2bit(tag); +    if (!tmpmask) +        return 0; +    *pmask |= tmpmask; +    return 1; +} + +int ASN1_str2mask(const char *str, unsigned long *pmask) +{ +    *pmask = 0; +    return CONF_parse_list(str, '|', 1, mask_cb, pmask); +} diff --git a/openssl-1.1.0h/crypto/asn1/asn1_lib.c b/openssl-1.1.0h/crypto/asn1/asn1_lib.c new file mode 100644 index 0000000..8ca53b4 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn1_lib.c @@ -0,0 +1,384 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <limits.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include "asn1_locl.h" + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, +                           long max); +static void asn1_put_length(unsigned char **pp, int length); + +static int _asn1_check_infinite_end(const unsigned char **p, long len) +{ +    /* +     * If there is 0 or 1 byte left, the length check should pick things up +     */ +    if (len <= 0) +        return (1); +    else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) { +        (*p) += 2; +        return (1); +    } +    return (0); +} + +int ASN1_check_infinite_end(unsigned char **p, long len) +{ +    return _asn1_check_infinite_end((const unsigned char **)p, len); +} + +int ASN1_const_check_infinite_end(const unsigned char **p, long len) +{ +    return _asn1_check_infinite_end(p, len); +} + +int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, +                    int *pclass, long omax) +{ +    int i, ret; +    long l; +    const unsigned char *p = *pp; +    int tag, xclass, inf; +    long max = omax; + +    if (!max) +        goto err; +    ret = (*p & V_ASN1_CONSTRUCTED); +    xclass = (*p & V_ASN1_PRIVATE); +    i = *p & V_ASN1_PRIMITIVE_TAG; +    if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ +        p++; +        if (--max == 0) +            goto err; +        l = 0; +        while (*p & 0x80) { +            l <<= 7L; +            l |= *(p++) & 0x7f; +            if (--max == 0) +                goto err; +            if (l > (INT_MAX >> 7L)) +                goto err; +        } +        l <<= 7L; +        l |= *(p++) & 0x7f; +        tag = (int)l; +        if (--max == 0) +            goto err; +    } else { +        tag = i; +        p++; +        if (--max == 0) +            goto err; +    } +    *ptag = tag; +    *pclass = xclass; +    if (!asn1_get_length(&p, &inf, plength, max)) +        goto err; + +    if (inf && !(ret & V_ASN1_CONSTRUCTED)) +        goto err; + +    if (*plength > (omax - (p - *pp))) { +        ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG); +        /* +         * Set this so that even if things are not long enough the values are +         * set correctly +         */ +        ret |= 0x80; +    } +    *pp = p; +    return (ret | inf); + err: +    ASN1err(ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG); +    return (0x80); +} + +static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, +                           long max) +{ +    const unsigned char *p = *pp; +    unsigned long ret = 0; +    unsigned long i; + +    if (max-- < 1) +        return 0; +    if (*p == 0x80) { +        *inf = 1; +        ret = 0; +        p++; +    } else { +        *inf = 0; +        i = *p & 0x7f; +        if (*(p++) & 0x80) { +            if (max < (long)i + 1) +                return 0; +            /* Skip leading zeroes */ +            while (i && *p == 0) { +                p++; +                i--; +            } +            if (i > sizeof(long)) +                return 0; +            while (i-- > 0) { +                ret <<= 8L; +                ret |= *(p++); +            } +        } else +            ret = i; +    } +    if (ret > LONG_MAX) +        return 0; +    *pp = p; +    *rl = (long)ret; +    return 1; +} + +/* + * class 0 is constructed constructed == 2 for indefinite length constructed + */ +void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, +                     int xclass) +{ +    unsigned char *p = *pp; +    int i, ttag; + +    i = (constructed) ? V_ASN1_CONSTRUCTED : 0; +    i |= (xclass & V_ASN1_PRIVATE); +    if (tag < 31) +        *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); +    else { +        *(p++) = i | V_ASN1_PRIMITIVE_TAG; +        for (i = 0, ttag = tag; ttag > 0; i++) +            ttag >>= 7; +        ttag = i; +        while (i-- > 0) { +            p[i] = tag & 0x7f; +            if (i != (ttag - 1)) +                p[i] |= 0x80; +            tag >>= 7; +        } +        p += ttag; +    } +    if (constructed == 2) +        *(p++) = 0x80; +    else +        asn1_put_length(&p, length); +    *pp = p; +} + +int ASN1_put_eoc(unsigned char **pp) +{ +    unsigned char *p = *pp; +    *p++ = 0; +    *p++ = 0; +    *pp = p; +    return 2; +} + +static void asn1_put_length(unsigned char **pp, int length) +{ +    unsigned char *p = *pp; +    int i, l; +    if (length <= 127) +        *(p++) = (unsigned char)length; +    else { +        l = length; +        for (i = 0; l > 0; i++) +            l >>= 8; +        *(p++) = i | 0x80; +        l = i; +        while (i-- > 0) { +            p[i] = length & 0xff; +            length >>= 8; +        } +        p += l; +    } +    *pp = p; +} + +int ASN1_object_size(int constructed, int length, int tag) +{ +    int ret = 1; +    if (length < 0) +        return -1; +    if (tag >= 31) { +        while (tag > 0) { +            tag >>= 7; +            ret++; +        } +    } +    if (constructed == 2) { +        ret += 3; +    } else { +        ret++; +        if (length > 127) { +            int tmplen = length; +            while (tmplen > 0) { +                tmplen >>= 8; +                ret++; +            } +        } +    } +    if (ret >= INT_MAX - length) +        return -1; +    return ret + length; +} + +int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) +{ +    if (str == NULL) +        return 0; +    dst->type = str->type; +    if (!ASN1_STRING_set(dst, str->data, str->length)) +        return 0; +    /* Copy flags but preserve embed value */ +    dst->flags &= ASN1_STRING_FLAG_EMBED; +    dst->flags |= str->flags & ~ASN1_STRING_FLAG_EMBED; +    return 1; +} + +ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) +{ +    ASN1_STRING *ret; +    if (!str) +        return NULL; +    ret = ASN1_STRING_new(); +    if (ret == NULL) +        return NULL; +    if (!ASN1_STRING_copy(ret, str)) { +        ASN1_STRING_free(ret); +        return NULL; +    } +    return ret; +} + +int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) +{ +    unsigned char *c; +    const char *data = _data; + +    if (len < 0) { +        if (data == NULL) +            return (0); +        else +            len = strlen(data); +    } +    if ((str->length <= len) || (str->data == NULL)) { +        c = str->data; +        str->data = OPENSSL_realloc(c, len + 1); +        if (str->data == NULL) { +            ASN1err(ASN1_F_ASN1_STRING_SET, ERR_R_MALLOC_FAILURE); +            str->data = c; +            return (0); +        } +    } +    str->length = len; +    if (data != NULL) { +        memcpy(str->data, data, len); +        /* an allowance for strings :-) */ +        str->data[len] = '\0'; +    } +    return (1); +} + +void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) +{ +    OPENSSL_free(str->data); +    str->data = data; +    str->length = len; +} + +ASN1_STRING *ASN1_STRING_new(void) +{ +    return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); +} + +ASN1_STRING *ASN1_STRING_type_new(int type) +{ +    ASN1_STRING *ret; + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) { +        ASN1err(ASN1_F_ASN1_STRING_TYPE_NEW, ERR_R_MALLOC_FAILURE); +        return (NULL); +    } +    ret->type = type; +    return (ret); +} + +void asn1_string_embed_free(ASN1_STRING *a, int embed) +{ +    if (a == NULL) +        return; +    if (!(a->flags & ASN1_STRING_FLAG_NDEF)) +        OPENSSL_free(a->data); +    if (embed == 0) +        OPENSSL_free(a); +} + +void ASN1_STRING_free(ASN1_STRING *a) +{ +    if (a == NULL) +        return; +    asn1_string_embed_free(a, a->flags & ASN1_STRING_FLAG_EMBED); +} + +void ASN1_STRING_clear_free(ASN1_STRING *a) +{ +    if (a == NULL) +        return; +    if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) +        OPENSSL_cleanse(a->data, a->length); +    ASN1_STRING_free(a); +} + +int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) +{ +    int i; + +    i = (a->length - b->length); +    if (i == 0) { +        i = memcmp(a->data, b->data, a->length); +        if (i == 0) +            return (a->type - b->type); +        else +            return (i); +    } else +        return (i); +} + +int ASN1_STRING_length(const ASN1_STRING *x) +{ +    return x->length; +} + +void ASN1_STRING_length_set(ASN1_STRING *x, int len) +{ +    x->length = len; +} + +int ASN1_STRING_type(const ASN1_STRING *x) +{ +    return x->type; +} + +const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) +{ +    return x->data; +} + +# if OPENSSL_API_COMPAT < 0x10100000L +unsigned char *ASN1_STRING_data(ASN1_STRING *x) +{ +    return x->data; +} +#endif diff --git a/openssl-1.1.0h/crypto/asn1/asn1_locl.h b/openssl-1.1.0h/crypto/asn1/asn1_locl.h new file mode 100644 index 0000000..9a47b1e --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn1_locl.h @@ -0,0 +1,83 @@ +/* + * Copyright 2005-2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* Internal ASN1 structures and functions: not for application use */ + +int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d); +int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d); + +/* ASN1 scan context structure */ + +struct asn1_sctx_st { +    /* The ASN1_ITEM associated with this field */ +    const ASN1_ITEM *it; +    /* If ASN1_TEMPLATE associated with this field */ +    const ASN1_TEMPLATE *tt; +    /* Various flags associated with field and context */ +    unsigned long flags; +    /* If SEQUENCE OF or SET OF, field index */ +    int skidx; +    /* ASN1 depth of field */ +    int depth; +    /* Structure and field name */ +    const char *sname, *fname; +    /* If a primitive type the type of underlying field */ +    int prim_type; +    /* The field value itself */ +    ASN1_VALUE **field; +    /* Callback to pass information to */ +    int (*scan_cb) (ASN1_SCTX *ctx); +    /* Context specific application data */ +    void *app_data; +} /* ASN1_SCTX */ ; + +typedef struct mime_param_st MIME_PARAM; +DEFINE_STACK_OF(MIME_PARAM) +typedef struct mime_header_st MIME_HEADER; +DEFINE_STACK_OF(MIME_HEADER) + +/* Month values for printing out times */ +extern const char *_asn1_mon[12]; + +void asn1_string_embed_free(ASN1_STRING *a, int embed); + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, +                             const ASN1_ITEM *it); + +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, +                                 int nullerr); + +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it); + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it); +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it); +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, +                     const ASN1_ITEM *it); +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, +                  const ASN1_ITEM *it); + +void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed); +void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); + +ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp, +                             long length); +int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp); +ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a, +                                     const unsigned char **pp, long length); +int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp); +ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp, +                               long length); + +/* Internal functions used by x_int64.c */ +int c2i_uint64_int(uint64_t *ret, int *neg, const unsigned char **pp, long len); +int i2c_uint64_int(unsigned char *p, uint64_t r, int neg); diff --git a/openssl-1.1.0h/crypto/asn1/asn1_par.c b/openssl-1.1.0h/crypto/asn1/asn1_par.c new file mode 100644 index 0000000..fabc8d6 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn1_par.c @@ -0,0 +1,375 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/objects.h> +#include <openssl/asn1.h> + +#ifndef ASN1_PARSE_MAXDEPTH +#define ASN1_PARSE_MAXDEPTH 128 +#endif + +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, +                           int indent); +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, +                       int offset, int depth, int indent, int dump); +static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed, +                           int indent) +{ +    static const char fmt[] = "%-18s"; +    char str[128]; +    const char *p; + +    if (constructed & V_ASN1_CONSTRUCTED) +        p = "cons: "; +    else +        p = "prim: "; +    if (BIO_write(bp, p, 6) < 6) +        goto err; +    BIO_indent(bp, indent, 128); + +    p = str; +    if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE) +        BIO_snprintf(str, sizeof(str), "priv [ %d ] ", tag); +    else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC) +        BIO_snprintf(str, sizeof(str), "cont [ %d ]", tag); +    else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION) +        BIO_snprintf(str, sizeof(str), "appl [ %d ]", tag); +    else if (tag > 30) +        BIO_snprintf(str, sizeof(str), "<ASN1 %d>", tag); +    else +        p = ASN1_tag2str(tag); + +    if (BIO_printf(bp, fmt, p) <= 0) +        goto err; +    return (1); + err: +    return (0); +} + +int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent) +{ +    return (asn1_parse2(bp, &pp, len, 0, 0, indent, 0)); +} + +int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, +                    int dump) +{ +    return (asn1_parse2(bp, &pp, len, 0, 0, indent, dump)); +} + +static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, +                       int offset, int depth, int indent, int dump) +{ +    const unsigned char *p, *ep, *tot, *op, *opp; +    long len; +    int tag, xclass, ret = 0; +    int nl, hl, j, r; +    ASN1_OBJECT *o = NULL; +    ASN1_OCTET_STRING *os = NULL; +    /* ASN1_BMPSTRING *bmp=NULL; */ +    int dump_indent, dump_cont = 0; + +    if (depth > ASN1_PARSE_MAXDEPTH) { +        BIO_puts(bp, "BAD RECURSION DEPTH\n"); +        return 0; +    } + +    dump_indent = 6;            /* Because we know BIO_dump_indent() */ +    p = *pp; +    tot = p + length; +    while (length > 0) { +        op = p; +        j = ASN1_get_object(&p, &len, &tag, &xclass, length); +        if (j & 0x80) { +            if (BIO_write(bp, "Error in encoding\n", 18) <= 0) +                goto end; +            ret = 0; +            goto end; +        } +        hl = (p - op); +        length -= hl; +        /* +         * if j == 0x21 it is a constructed indefinite length object +         */ +        if (BIO_printf(bp, "%5ld:", (long)offset + (long)(op - *pp)) +            <= 0) +            goto end; + +        if (j != (V_ASN1_CONSTRUCTED | 1)) { +            if (BIO_printf(bp, "d=%-2d hl=%ld l=%4ld ", +                           depth, (long)hl, len) <= 0) +                goto end; +        } else { +            if (BIO_printf(bp, "d=%-2d hl=%ld l=inf  ", depth, (long)hl) <= 0) +                goto end; +        } +        if (!asn1_print_info(bp, tag, xclass, j, (indent) ? depth : 0)) +            goto end; +        if (j & V_ASN1_CONSTRUCTED) { +            const unsigned char *sp = p; + +            ep = p + len; +            if (BIO_write(bp, "\n", 1) <= 0) +                goto end; +            if (len > length) { +                BIO_printf(bp, "length is greater than %ld\n", length); +                ret = 0; +                goto end; +            } +            if ((j == 0x21) && (len == 0)) { +                for (;;) { +                    r = asn1_parse2(bp, &p, (long)(tot - p), +                                    offset + (p - *pp), depth + 1, +                                    indent, dump); +                    if (r == 0) { +                        ret = 0; +                        goto end; +                    } +                    if ((r == 2) || (p >= tot)) { +                        len = p - sp; +                        break; +                    } +                } +            } else { +                long tmp = len; + +                while (p < ep) { +                    sp = p; +                    r = asn1_parse2(bp, &p, tmp, +                                    offset + (p - *pp), depth + 1, +                                    indent, dump); +                    if (r == 0) { +                        ret = 0; +                        goto end; +                    } +                    tmp -= p - sp; +                } +            } +        } else if (xclass != 0) { +            p += len; +            if (BIO_write(bp, "\n", 1) <= 0) +                goto end; +        } else { +            nl = 0; +            if ((tag == V_ASN1_PRINTABLESTRING) || +                (tag == V_ASN1_T61STRING) || +                (tag == V_ASN1_IA5STRING) || +                (tag == V_ASN1_VISIBLESTRING) || +                (tag == V_ASN1_NUMERICSTRING) || +                (tag == V_ASN1_UTF8STRING) || +                (tag == V_ASN1_UTCTIME) || (tag == V_ASN1_GENERALIZEDTIME)) { +                if (BIO_write(bp, ":", 1) <= 0) +                    goto end; +                if ((len > 0) && BIO_write(bp, (const char *)p, (int)len) +                    != (int)len) +                    goto end; +            } else if (tag == V_ASN1_OBJECT) { +                opp = op; +                if (d2i_ASN1_OBJECT(&o, &opp, len + hl) != NULL) { +                    if (BIO_write(bp, ":", 1) <= 0) +                        goto end; +                    i2a_ASN1_OBJECT(bp, o); +                } else { +                    if (BIO_puts(bp, ":BAD OBJECT") <= 0) +                        goto end; +                    dump_cont = 1; +                } +            } else if (tag == V_ASN1_BOOLEAN) { +                if (len != 1) { +                    if (BIO_puts(bp, ":BAD BOOLEAN") <= 0) +                        goto end; +                    dump_cont = 1; +                } +                if (len > 0) +                    BIO_printf(bp, ":%u", p[0]); +            } else if (tag == V_ASN1_BMPSTRING) { +                /* do the BMP thang */ +            } else if (tag == V_ASN1_OCTET_STRING) { +                int i, printable = 1; + +                opp = op; +                os = d2i_ASN1_OCTET_STRING(NULL, &opp, len + hl); +                if (os != NULL && os->length > 0) { +                    opp = os->data; +                    /* +                     * testing whether the octet string is printable +                     */ +                    for (i = 0; i < os->length; i++) { +                        if (((opp[i] < ' ') && +                             (opp[i] != '\n') && +                             (opp[i] != '\r') && +                             (opp[i] != '\t')) || (opp[i] > '~')) { +                            printable = 0; +                            break; +                        } +                    } +                    if (printable) +                        /* printable string */ +                    { +                        if (BIO_write(bp, ":", 1) <= 0) +                            goto end; +                        if (BIO_write(bp, (const char *)opp, os->length) <= 0) +                            goto end; +                    } else if (!dump) +                        /* +                         * not printable => print octet string as hex dump +                         */ +                    { +                        if (BIO_write(bp, "[HEX DUMP]:", 11) <= 0) +                            goto end; +                        for (i = 0; i < os->length; i++) { +                            if (BIO_printf(bp, "%02X", opp[i]) <= 0) +                                goto end; +                        } +                    } else +                        /* print the normal dump */ +                    { +                        if (!nl) { +                            if (BIO_write(bp, "\n", 1) <= 0) +                                goto end; +                        } +                        if (BIO_dump_indent(bp, +                                            (const char *)opp, +                                            ((dump == -1 || dump > +                                              os-> +                                              length) ? os->length : dump), +                                            dump_indent) <= 0) +                            goto end; +                        nl = 1; +                    } +                } +                ASN1_OCTET_STRING_free(os); +                os = NULL; +            } else if (tag == V_ASN1_INTEGER) { +                ASN1_INTEGER *bs; +                int i; + +                opp = op; +                bs = d2i_ASN1_INTEGER(NULL, &opp, len + hl); +                if (bs != NULL) { +                    if (BIO_write(bp, ":", 1) <= 0) +                        goto end; +                    if (bs->type == V_ASN1_NEG_INTEGER) +                        if (BIO_write(bp, "-", 1) <= 0) +                            goto end; +                    for (i = 0; i < bs->length; i++) { +                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0) +                            goto end; +                    } +                    if (bs->length == 0) { +                        if (BIO_write(bp, "00", 2) <= 0) +                            goto end; +                    } +                } else { +                    if (BIO_puts(bp, ":BAD INTEGER") <= 0) +                        goto end; +                    dump_cont = 1; +                } +                ASN1_INTEGER_free(bs); +            } else if (tag == V_ASN1_ENUMERATED) { +                ASN1_ENUMERATED *bs; +                int i; + +                opp = op; +                bs = d2i_ASN1_ENUMERATED(NULL, &opp, len + hl); +                if (bs != NULL) { +                    if (BIO_write(bp, ":", 1) <= 0) +                        goto end; +                    if (bs->type == V_ASN1_NEG_ENUMERATED) +                        if (BIO_write(bp, "-", 1) <= 0) +                            goto end; +                    for (i = 0; i < bs->length; i++) { +                        if (BIO_printf(bp, "%02X", bs->data[i]) <= 0) +                            goto end; +                    } +                    if (bs->length == 0) { +                        if (BIO_write(bp, "00", 2) <= 0) +                            goto end; +                    } +                } else { +                    if (BIO_puts(bp, ":BAD ENUMERATED") <= 0) +                        goto end; +                    dump_cont = 1; +                } +                ASN1_ENUMERATED_free(bs); +            } else if (len > 0 && dump) { +                if (!nl) { +                    if (BIO_write(bp, "\n", 1) <= 0) +                        goto end; +                } +                if (BIO_dump_indent(bp, (const char *)p, +                                    ((dump == -1 || dump > len) ? len : dump), +                                    dump_indent) <= 0) +                    goto end; +                nl = 1; +            } +            if (dump_cont) { +                int i; +                const unsigned char *tmp = op + hl; +                if (BIO_puts(bp, ":[") <= 0) +                    goto end; +                for (i = 0; i < len; i++) { +                    if (BIO_printf(bp, "%02X", tmp[i]) <= 0) +                        goto end; +                } +                if (BIO_puts(bp, "]") <= 0) +                    goto end; +            } + +            if (!nl) { +                if (BIO_write(bp, "\n", 1) <= 0) +                    goto end; +            } +            p += len; +            if ((tag == V_ASN1_EOC) && (xclass == 0)) { +                ret = 2;        /* End of sequence */ +                goto end; +            } +        } +        length -= len; +    } +    ret = 1; + end: +    ASN1_OBJECT_free(o); +    ASN1_OCTET_STRING_free(os); +    *pp = p; +    return (ret); +} + +const char *ASN1_tag2str(int tag) +{ +    static const char *const tag2str[] = { +        /* 0-4 */ +        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", +        /* 5-9 */ +        "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", +        /* 10-13 */ +        "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", +        /* 15-17 */ +        "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", +        /* 18-20 */ +        "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", +        /* 21-24 */ +        "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", +        /* 25-27 */ +        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", +        /* 28-30 */ +        "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" +    }; + +    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) +        tag &= ~0x100; + +    if (tag < 0 || tag > 30) +        return "(unknown)"; +    return tag2str[tag]; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn_mime.c b/openssl-1.1.0h/crypto/asn1/asn_mime.c new file mode 100644 index 0000000..84475e9 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn_mime.c @@ -0,0 +1,981 @@ +/* + * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/rand.h> +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include "internal/evp_int.h" +#include "internal/bio.h" +#include "asn1_locl.h" + +/* + * Generalised MIME like utilities for streaming ASN1. Although many have a + * PKCS7/CMS like flavour others are more general purpose. + */ + +/* + * MIME format structures Note that all are translated to lower case apart + * from parameter values. Quotes are stripped off + */ + +struct mime_param_st { +    char *param_name;           /* Param name e.g. "micalg" */ +    char *param_value;          /* Param value e.g. "sha1" */ +}; + +struct mime_header_st { +    char *name;                 /* Name of line e.g. "content-type" */ +    char *value;                /* Value of line e.g. "text/plain" */ +    STACK_OF(MIME_PARAM) *params; /* Zero or more parameters */ +}; + +static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, +                            const ASN1_ITEM *it); +static char *strip_ends(char *name); +static char *strip_start(char *name); +static char *strip_end(char *name); +static MIME_HEADER *mime_hdr_new(const char *name, const char *value); +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value); +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio); +static int mime_hdr_cmp(const MIME_HEADER *const *a, +                        const MIME_HEADER *const *b); +static int mime_param_cmp(const MIME_PARAM *const *a, +                          const MIME_PARAM *const *b); +static void mime_param_free(MIME_PARAM *param); +static int mime_bound_check(char *line, int linelen, const char *bound, int blen); +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret); +static int strip_eol(char *linebuf, int *plen, int flags); +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name); +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name); +static void mime_hdr_free(MIME_HEADER *hdr); + +#define MAX_SMLEN 1024 +#define mime_debug(x)           /* x */ + +/* Output an ASN1 structure in BER format streaming if necessary */ + +int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, +                        const ASN1_ITEM *it) +{ +    /* If streaming create stream BIO and copy all content through it */ +    if (flags & SMIME_STREAM) { +        BIO *bio, *tbio; +        bio = BIO_new_NDEF(out, val, it); +        if (!bio) { +            ASN1err(ASN1_F_I2D_ASN1_BIO_STREAM, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        SMIME_crlf_copy(in, bio, flags); +        (void)BIO_flush(bio); +        /* Free up successive BIOs until we hit the old output BIO */ +        do { +            tbio = BIO_pop(bio); +            BIO_free(bio); +            bio = tbio; +        } while (bio != out); +    } +    /* +     * else just write out ASN1 structure which will have all content stored +     * internally +     */ +    else +        ASN1_item_i2d_bio(it, out, val); +    return 1; +} + +/* Base 64 read and write of ASN1 structure */ + +static int B64_write_ASN1(BIO *out, ASN1_VALUE *val, BIO *in, int flags, +                          const ASN1_ITEM *it) +{ +    BIO *b64; +    int r; +    b64 = BIO_new(BIO_f_base64()); +    if (b64 == NULL) { +        ASN1err(ASN1_F_B64_WRITE_ASN1, ERR_R_MALLOC_FAILURE); +        return 0; +    } +    /* +     * prepend the b64 BIO so all data is base64 encoded. +     */ +    out = BIO_push(b64, out); +    r = i2d_ASN1_bio_stream(out, val, in, flags, it); +    (void)BIO_flush(out); +    BIO_pop(out); +    BIO_free(b64); +    return r; +} + +/* Streaming ASN1 PEM write */ + +int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, +                              const char *hdr, const ASN1_ITEM *it) +{ +    int r; +    BIO_printf(out, "-----BEGIN %s-----\n", hdr); +    r = B64_write_ASN1(out, val, in, flags, it); +    BIO_printf(out, "-----END %s-----\n", hdr); +    return r; +} + +static ASN1_VALUE *b64_read_asn1(BIO *bio, const ASN1_ITEM *it) +{ +    BIO *b64; +    ASN1_VALUE *val; + +    if ((b64 = BIO_new(BIO_f_base64())) == NULL) { +        ASN1err(ASN1_F_B64_READ_ASN1, ERR_R_MALLOC_FAILURE); +        return 0; +    } +    bio = BIO_push(b64, bio); +    val = ASN1_item_d2i_bio(it, bio, NULL); +    if (!val) +        ASN1err(ASN1_F_B64_READ_ASN1, ASN1_R_DECODE_ERROR); +    (void)BIO_flush(bio); +    BIO_pop(bio); +    BIO_free(b64); +    return val; +} + +/* Generate the MIME "micalg" parameter from RFC3851, RFC4490 */ + +static int asn1_write_micalg(BIO *out, STACK_OF(X509_ALGOR) *mdalgs) +{ +    const EVP_MD *md; +    int i, have_unknown = 0, write_comma, ret = 0, md_nid; +    have_unknown = 0; +    write_comma = 0; +    for (i = 0; i < sk_X509_ALGOR_num(mdalgs); i++) { +        if (write_comma) +            BIO_write(out, ",", 1); +        write_comma = 1; +        md_nid = OBJ_obj2nid(sk_X509_ALGOR_value(mdalgs, i)->algorithm); +        md = EVP_get_digestbynid(md_nid); +        if (md && md->md_ctrl) { +            int rv; +            char *micstr; +            rv = md->md_ctrl(NULL, EVP_MD_CTRL_MICALG, 0, &micstr); +            if (rv > 0) { +                BIO_puts(out, micstr); +                OPENSSL_free(micstr); +                continue; +            } +            if (rv != -2) +                goto err; +        } +        switch (md_nid) { +        case NID_sha1: +            BIO_puts(out, "sha1"); +            break; + +        case NID_md5: +            BIO_puts(out, "md5"); +            break; + +        case NID_sha256: +            BIO_puts(out, "sha-256"); +            break; + +        case NID_sha384: +            BIO_puts(out, "sha-384"); +            break; + +        case NID_sha512: +            BIO_puts(out, "sha-512"); +            break; + +        case NID_id_GostR3411_94: +            BIO_puts(out, "gostr3411-94"); +            goto err; + +        default: +            if (have_unknown) +                write_comma = 0; +            else { +                BIO_puts(out, "unknown"); +                have_unknown = 1; +            } +            break; + +        } +    } + +    ret = 1; + err: + +    return ret; + +} + +/* SMIME sender */ + +int SMIME_write_ASN1(BIO *bio, ASN1_VALUE *val, BIO *data, int flags, +                     int ctype_nid, int econt_nid, +                     STACK_OF(X509_ALGOR) *mdalgs, const ASN1_ITEM *it) +{ +    char bound[33], c; +    int i; +    const char *mime_prefix, *mime_eol, *cname = "smime.p7m"; +    const char *msg_type = NULL; +    if (flags & SMIME_OLDMIME) +        mime_prefix = "application/x-pkcs7-"; +    else +        mime_prefix = "application/pkcs7-"; + +    if (flags & SMIME_CRLFEOL) +        mime_eol = "\r\n"; +    else +        mime_eol = "\n"; +    if ((flags & SMIME_DETACHED) && data) { +        /* We want multipart/signed */ +        /* Generate a random boundary */ +        if (RAND_bytes((unsigned char *)bound, 32) <= 0) +            return 0; +        for (i = 0; i < 32; i++) { +            c = bound[i] & 0xf; +            if (c < 10) +                c += '0'; +            else +                c += 'A' - 10; +            bound[i] = c; +        } +        bound[32] = 0; +        BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); +        BIO_printf(bio, "Content-Type: multipart/signed;"); +        BIO_printf(bio, " protocol=\"%ssignature\";", mime_prefix); +        BIO_puts(bio, " micalg=\""); +        asn1_write_micalg(bio, mdalgs); +        BIO_printf(bio, "\"; boundary=\"----%s\"%s%s", +                   bound, mime_eol, mime_eol); +        BIO_printf(bio, "This is an S/MIME signed message%s%s", +                   mime_eol, mime_eol); +        /* Now write out the first part */ +        BIO_printf(bio, "------%s%s", bound, mime_eol); +        if (!asn1_output_data(bio, data, val, flags, it)) +            return 0; +        BIO_printf(bio, "%s------%s%s", mime_eol, bound, mime_eol); + +        /* Headers for signature */ + +        BIO_printf(bio, "Content-Type: %ssignature;", mime_prefix); +        BIO_printf(bio, " name=\"smime.p7s\"%s", mime_eol); +        BIO_printf(bio, "Content-Transfer-Encoding: base64%s", mime_eol); +        BIO_printf(bio, "Content-Disposition: attachment;"); +        BIO_printf(bio, " filename=\"smime.p7s\"%s%s", mime_eol, mime_eol); +        B64_write_ASN1(bio, val, NULL, 0, it); +        BIO_printf(bio, "%s------%s--%s%s", mime_eol, bound, +                   mime_eol, mime_eol); +        return 1; +    } + +    /* Determine smime-type header */ + +    if (ctype_nid == NID_pkcs7_enveloped) +        msg_type = "enveloped-data"; +    else if (ctype_nid == NID_pkcs7_signed) { +        if (econt_nid == NID_id_smime_ct_receipt) +            msg_type = "signed-receipt"; +        else if (sk_X509_ALGOR_num(mdalgs) >= 0) +            msg_type = "signed-data"; +        else +            msg_type = "certs-only"; +    } else if (ctype_nid == NID_id_smime_ct_compressedData) { +        msg_type = "compressed-data"; +        cname = "smime.p7z"; +    } +    /* MIME headers */ +    BIO_printf(bio, "MIME-Version: 1.0%s", mime_eol); +    BIO_printf(bio, "Content-Disposition: attachment;"); +    BIO_printf(bio, " filename=\"%s\"%s", cname, mime_eol); +    BIO_printf(bio, "Content-Type: %smime;", mime_prefix); +    if (msg_type) +        BIO_printf(bio, " smime-type=%s;", msg_type); +    BIO_printf(bio, " name=\"%s\"%s", cname, mime_eol); +    BIO_printf(bio, "Content-Transfer-Encoding: base64%s%s", +               mime_eol, mime_eol); +    if (!B64_write_ASN1(bio, val, data, flags, it)) +        return 0; +    BIO_printf(bio, "%s", mime_eol); +    return 1; +} + +/* Handle output of ASN1 data */ + +static int asn1_output_data(BIO *out, BIO *data, ASN1_VALUE *val, int flags, +                            const ASN1_ITEM *it) +{ +    BIO *tmpbio; +    const ASN1_AUX *aux = it->funcs; +    ASN1_STREAM_ARG sarg; +    int rv = 1; + +    /* +     * If data is not detached or resigning then the output BIO is already +     * set up to finalise when it is written through. +     */ +    if (!(flags & SMIME_DETACHED) || (flags & PKCS7_REUSE_DIGEST)) { +        SMIME_crlf_copy(data, out, flags); +        return 1; +    } + +    if (!aux || !aux->asn1_cb) { +        ASN1err(ASN1_F_ASN1_OUTPUT_DATA, ASN1_R_STREAMING_NOT_SUPPORTED); +        return 0; +    } + +    sarg.out = out; +    sarg.ndef_bio = NULL; +    sarg.boundary = NULL; + +    /* Let ASN1 code prepend any needed BIOs */ + +    if (aux->asn1_cb(ASN1_OP_DETACHED_PRE, &val, it, &sarg) <= 0) +        return 0; + +    /* Copy data across, passing through filter BIOs for processing */ +    SMIME_crlf_copy(data, sarg.ndef_bio, flags); + +    /* Finalize structure */ +    if (aux->asn1_cb(ASN1_OP_DETACHED_POST, &val, it, &sarg) <= 0) +        rv = 0; + +    /* Now remove any digests prepended to the BIO */ + +    while (sarg.ndef_bio != out) { +        tmpbio = BIO_pop(sarg.ndef_bio); +        BIO_free(sarg.ndef_bio); +        sarg.ndef_bio = tmpbio; +    } + +    return rv; + +} + +/* + * SMIME reader: handle multipart/signed and opaque signing. in multipart + * case the content is placed in a memory BIO pointed to by "bcont". In + * opaque this is set to NULL + */ + +ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it) +{ +    BIO *asnin; +    STACK_OF(MIME_HEADER) *headers = NULL; +    STACK_OF(BIO) *parts = NULL; +    MIME_HEADER *hdr; +    MIME_PARAM *prm; +    ASN1_VALUE *val; +    int ret; + +    if (bcont) +        *bcont = NULL; + +    if ((headers = mime_parse_hdr(bio)) == NULL) { +        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_PARSE_ERROR); +        return NULL; +    } + +    if ((hdr = mime_hdr_find(headers, "content-type")) == NULL +        || hdr->value == NULL) { +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_CONTENT_TYPE); +        return NULL; +    } + +    /* Handle multipart/signed */ + +    if (strcmp(hdr->value, "multipart/signed") == 0) { +        /* Split into two parts */ +        prm = mime_param_find(hdr, "boundary"); +        if (!prm || !prm->param_value) { +            sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BOUNDARY); +            return NULL; +        } +        ret = multi_split(bio, prm->param_value, &parts); +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        if (!ret || (sk_BIO_num(parts) != 2)) { +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_MULTIPART_BODY_FAILURE); +            sk_BIO_pop_free(parts, BIO_vfree); +            return NULL; +        } + +        /* Parse the signature piece */ +        asnin = sk_BIO_value(parts, 1); + +        if ((headers = mime_parse_hdr(asnin)) == NULL) { +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_MIME_SIG_PARSE_ERROR); +            sk_BIO_pop_free(parts, BIO_vfree); +            return NULL; +        } + +        /* Get content type */ + +        if ((hdr = mime_hdr_find(headers, "content-type")) == NULL +            || hdr->value == NULL) { +            sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_NO_SIG_CONTENT_TYPE); +            sk_BIO_pop_free(parts, BIO_vfree); +            return NULL; +        } + +        if (strcmp(hdr->value, "application/x-pkcs7-signature") && +            strcmp(hdr->value, "application/pkcs7-signature")) { +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_SIG_INVALID_MIME_TYPE); +            ERR_add_error_data(2, "type: ", hdr->value); +            sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +            sk_BIO_pop_free(parts, BIO_vfree); +            return NULL; +        } +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        /* Read in ASN1 */ +        if ((val = b64_read_asn1(asnin, it)) == NULL) { +            ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_SIG_PARSE_ERROR); +            sk_BIO_pop_free(parts, BIO_vfree); +            return NULL; +        } + +        if (bcont) { +            *bcont = sk_BIO_value(parts, 0); +            BIO_free(asnin); +            sk_BIO_free(parts); +        } else +            sk_BIO_pop_free(parts, BIO_vfree); +        return val; +    } + +    /* OK, if not multipart/signed try opaque signature */ + +    if (strcmp(hdr->value, "application/x-pkcs7-mime") && +        strcmp(hdr->value, "application/pkcs7-mime")) { +        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_INVALID_MIME_TYPE); +        ERR_add_error_data(2, "type: ", hdr->value); +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        return NULL; +    } + +    sk_MIME_HEADER_pop_free(headers, mime_hdr_free); + +    if ((val = b64_read_asn1(bio, it)) == NULL) { +        ASN1err(ASN1_F_SMIME_READ_ASN1, ASN1_R_ASN1_PARSE_ERROR); +        return NULL; +    } +    return val; + +} + +/* Copy text from one BIO to another making the output CRLF at EOL */ +int SMIME_crlf_copy(BIO *in, BIO *out, int flags) +{ +    BIO *bf; +    char eol; +    int len; +    char linebuf[MAX_SMLEN]; +    /* +     * Buffer output so we don't write one line at a time. This is useful +     * when streaming as we don't end up with one OCTET STRING per line. +     */ +    bf = BIO_new(BIO_f_buffer()); +    if (bf == NULL) +        return 0; +    out = BIO_push(bf, out); +    if (flags & SMIME_BINARY) { +        while ((len = BIO_read(in, linebuf, MAX_SMLEN)) > 0) +            BIO_write(out, linebuf, len); +    } else { +        int eolcnt = 0; +        if (flags & SMIME_TEXT) +            BIO_printf(out, "Content-Type: text/plain\r\n\r\n"); +        while ((len = BIO_gets(in, linebuf, MAX_SMLEN)) > 0) { +            eol = strip_eol(linebuf, &len, flags); +            if (len) { +                /* Not EOF: write out all CRLF */ +                if (flags & SMIME_ASCIICRLF) { +                    int i; +                    for (i = 0; i < eolcnt; i++) +                        BIO_write(out, "\r\n", 2); +                    eolcnt = 0; +                } +                BIO_write(out, linebuf, len); +                if (eol) +                    BIO_write(out, "\r\n", 2); +            } else if (flags & SMIME_ASCIICRLF) +                eolcnt++; +            else if (eol) +                BIO_write(out, "\r\n", 2); +        } +    } +    (void)BIO_flush(out); +    BIO_pop(out); +    BIO_free(bf); +    return 1; +} + +/* Strip off headers if they are text/plain */ +int SMIME_text(BIO *in, BIO *out) +{ +    char iobuf[4096]; +    int len; +    STACK_OF(MIME_HEADER) *headers; +    MIME_HEADER *hdr; + +    if ((headers = mime_parse_hdr(in)) == NULL) { +        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_PARSE_ERROR); +        return 0; +    } +    if ((hdr = mime_hdr_find(headers, "content-type")) == NULL +        || hdr->value == NULL) { +        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_MIME_NO_CONTENT_TYPE); +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        return 0; +    } +    if (strcmp(hdr->value, "text/plain")) { +        ASN1err(ASN1_F_SMIME_TEXT, ASN1_R_INVALID_MIME_TYPE); +        ERR_add_error_data(2, "type: ", hdr->value); +        sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +        return 0; +    } +    sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +    while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) +        BIO_write(out, iobuf, len); +    if (len < 0) +        return 0; +    return 1; +} + +/* + * Split a multipart/XXX message body into component parts: result is + * canonical parts in a STACK of bios + */ + +static int multi_split(BIO *bio, const char *bound, STACK_OF(BIO) **ret) +{ +    char linebuf[MAX_SMLEN]; +    int len, blen; +    int eol = 0, next_eol = 0; +    BIO *bpart = NULL; +    STACK_OF(BIO) *parts; +    char state, part, first; + +    blen = strlen(bound); +    part = 0; +    state = 0; +    first = 1; +    parts = sk_BIO_new_null(); +    *ret = parts; +    if (*ret == NULL) +        return 0; +    while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { +        state = mime_bound_check(linebuf, len, bound, blen); +        if (state == 1) { +            first = 1; +            part++; +        } else if (state == 2) { +            if (!sk_BIO_push(parts, bpart)) { +                BIO_free(bpart); +                return 0; +            } +            return 1; +        } else if (part) { +            /* Strip CR+LF from linebuf */ +            next_eol = strip_eol(linebuf, &len, 0); +            if (first) { +                first = 0; +                if (bpart) +                    if (!sk_BIO_push(parts, bpart)) { +                        BIO_free(bpart); +                        return 0; +                    } +                bpart = BIO_new(BIO_s_mem()); +                if (bpart == NULL) +                    return 0; +                BIO_set_mem_eof_return(bpart, 0); +            } else if (eol) +                BIO_write(bpart, "\r\n", 2); +            eol = next_eol; +            if (len) +                BIO_write(bpart, linebuf, len); +        } +    } +    BIO_free(bpart); +    return 0; +} + +/* This is the big one: parse MIME header lines up to message body */ + +#define MIME_INVALID    0 +#define MIME_START      1 +#define MIME_TYPE       2 +#define MIME_NAME       3 +#define MIME_VALUE      4 +#define MIME_QUOTE      5 +#define MIME_COMMENT    6 + +static STACK_OF(MIME_HEADER) *mime_parse_hdr(BIO *bio) +{ +    char *p, *q, c; +    char *ntmp; +    char linebuf[MAX_SMLEN]; +    MIME_HEADER *mhdr = NULL, *new_hdr = NULL; +    STACK_OF(MIME_HEADER) *headers; +    int len, state, save_state = 0; + +    headers = sk_MIME_HEADER_new(mime_hdr_cmp); +    if (headers == NULL) +        return NULL; +    while ((len = BIO_gets(bio, linebuf, MAX_SMLEN)) > 0) { +        /* If whitespace at line start then continuation line */ +        if (mhdr && isspace((unsigned char)linebuf[0])) +            state = MIME_NAME; +        else +            state = MIME_START; +        ntmp = NULL; +        /* Go through all characters */ +        for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n'); +             p++) { + +            /* +             * State machine to handle MIME headers if this looks horrible +             * that's because it *is* +             */ + +            switch (state) { +            case MIME_START: +                if (c == ':') { +                    state = MIME_TYPE; +                    *p = 0; +                    ntmp = strip_ends(q); +                    q = p + 1; +                } +                break; + +            case MIME_TYPE: +                if (c == ';') { +                    mime_debug("Found End Value\n"); +                    *p = 0; +                    new_hdr = mime_hdr_new(ntmp, strip_ends(q)); +                    if (new_hdr == NULL) +                        goto err; +                    if (!sk_MIME_HEADER_push(headers, new_hdr)) +                        goto err; +                    mhdr = new_hdr; +                    new_hdr = NULL; +                    ntmp = NULL; +                    q = p + 1; +                    state = MIME_NAME; +                } else if (c == '(') { +                    save_state = state; +                    state = MIME_COMMENT; +                } +                break; + +            case MIME_COMMENT: +                if (c == ')') { +                    state = save_state; +                } +                break; + +            case MIME_NAME: +                if (c == '=') { +                    state = MIME_VALUE; +                    *p = 0; +                    ntmp = strip_ends(q); +                    q = p + 1; +                } +                break; + +            case MIME_VALUE: +                if (c == ';') { +                    state = MIME_NAME; +                    *p = 0; +                    mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); +                    ntmp = NULL; +                    q = p + 1; +                } else if (c == '"') { +                    mime_debug("Found Quote\n"); +                    state = MIME_QUOTE; +                } else if (c == '(') { +                    save_state = state; +                    state = MIME_COMMENT; +                } +                break; + +            case MIME_QUOTE: +                if (c == '"') { +                    mime_debug("Found Match Quote\n"); +                    state = MIME_VALUE; +                } +                break; +            } +        } + +        if (state == MIME_TYPE) { +            new_hdr = mime_hdr_new(ntmp, strip_ends(q)); +            if (new_hdr == NULL) +                goto err; +            if (!sk_MIME_HEADER_push(headers, new_hdr)) +                goto err; +            mhdr = new_hdr; +            new_hdr = NULL; +        } else if (state == MIME_VALUE) +            mime_hdr_addparam(mhdr, ntmp, strip_ends(q)); +        if (p == linebuf) +            break;              /* Blank line means end of headers */ +    } + +    return headers; + +err: +    mime_hdr_free(new_hdr); +    sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +    return NULL; +} + +static char *strip_ends(char *name) +{ +    return strip_end(strip_start(name)); +} + +/* Strip a parameter of whitespace from start of param */ +static char *strip_start(char *name) +{ +    char *p, c; +    /* Look for first non white space or quote */ +    for (p = name; (c = *p); p++) { +        if (c == '"') { +            /* Next char is start of string if non null */ +            if (p[1]) +                return p + 1; +            /* Else null string */ +            return NULL; +        } +        if (!isspace((unsigned char)c)) +            return p; +    } +    return NULL; +} + +/* As above but strip from end of string : maybe should handle brackets? */ +static char *strip_end(char *name) +{ +    char *p, c; +    if (!name) +        return NULL; +    /* Look for first non white space or quote */ +    for (p = name + strlen(name) - 1; p >= name; p--) { +        c = *p; +        if (c == '"') { +            if (p - 1 == name) +                return NULL; +            *p = 0; +            return name; +        } +        if (isspace((unsigned char)c)) +            *p = 0; +        else +            return name; +    } +    return NULL; +} + +static MIME_HEADER *mime_hdr_new(const char *name, const char *value) +{ +    MIME_HEADER *mhdr = NULL; +    char *tmpname = NULL, *tmpval = NULL, *p; +    int c; + +    if (name) { +        if ((tmpname = OPENSSL_strdup(name)) == NULL) +            return NULL; +        for (p = tmpname; *p; p++) { +            c = (unsigned char)*p; +            if (isupper(c)) { +                c = tolower(c); +                *p = c; +            } +        } +    } +    if (value) { +        if ((tmpval = OPENSSL_strdup(value)) == NULL) +            goto err; +        for (p = tmpval; *p; p++) { +            c = (unsigned char)*p; +            if (isupper(c)) { +                c = tolower(c); +                *p = c; +            } +        } +    } +    mhdr = OPENSSL_malloc(sizeof(*mhdr)); +    if (mhdr == NULL) +        goto err; +    mhdr->name = tmpname; +    mhdr->value = tmpval; +    if ((mhdr->params = sk_MIME_PARAM_new(mime_param_cmp)) == NULL) +        goto err; +    return mhdr; + + err: +    OPENSSL_free(tmpname); +    OPENSSL_free(tmpval); +    OPENSSL_free(mhdr); +    return NULL; +} + +static int mime_hdr_addparam(MIME_HEADER *mhdr, const char *name, const char *value) +{ +    char *tmpname = NULL, *tmpval = NULL, *p; +    int c; +    MIME_PARAM *mparam = NULL; +    if (name) { +        tmpname = OPENSSL_strdup(name); +        if (!tmpname) +            goto err; +        for (p = tmpname; *p; p++) { +            c = (unsigned char)*p; +            if (isupper(c)) { +                c = tolower(c); +                *p = c; +            } +        } +    } +    if (value) { +        tmpval = OPENSSL_strdup(value); +        if (!tmpval) +            goto err; +    } +    /* Parameter values are case sensitive so leave as is */ +    mparam = OPENSSL_malloc(sizeof(*mparam)); +    if (mparam == NULL) +        goto err; +    mparam->param_name = tmpname; +    mparam->param_value = tmpval; +    if (!sk_MIME_PARAM_push(mhdr->params, mparam)) +        goto err; +    return 1; + err: +    OPENSSL_free(tmpname); +    OPENSSL_free(tmpval); +    OPENSSL_free(mparam); +    return 0; +} + +static int mime_hdr_cmp(const MIME_HEADER *const *a, +                        const MIME_HEADER *const *b) +{ +    if (!(*a)->name || !(*b)->name) +        return ! !(*a)->name - ! !(*b)->name; + +    return (strcmp((*a)->name, (*b)->name)); +} + +static int mime_param_cmp(const MIME_PARAM *const *a, +                          const MIME_PARAM *const *b) +{ +    if (!(*a)->param_name || !(*b)->param_name) +        return ! !(*a)->param_name - ! !(*b)->param_name; +    return (strcmp((*a)->param_name, (*b)->param_name)); +} + +/* Find a header with a given name (if possible) */ + +static MIME_HEADER *mime_hdr_find(STACK_OF(MIME_HEADER) *hdrs, const char *name) +{ +    MIME_HEADER htmp; +    int idx; + +    htmp.name = (char *)name; +    htmp.value = NULL; +    htmp.params = NULL; + +    idx = sk_MIME_HEADER_find(hdrs, &htmp); +    if (idx < 0) +        return NULL; +    return sk_MIME_HEADER_value(hdrs, idx); +} + +static MIME_PARAM *mime_param_find(MIME_HEADER *hdr, const char *name) +{ +    MIME_PARAM param; +    int idx; + +    param.param_name = (char *)name; +    param.param_value = NULL; +    idx = sk_MIME_PARAM_find(hdr->params, ¶m); +    if (idx < 0) +        return NULL; +    return sk_MIME_PARAM_value(hdr->params, idx); +} + +static void mime_hdr_free(MIME_HEADER *hdr) +{ +    if (hdr == NULL) +        return; +    OPENSSL_free(hdr->name); +    OPENSSL_free(hdr->value); +    if (hdr->params) +        sk_MIME_PARAM_pop_free(hdr->params, mime_param_free); +    OPENSSL_free(hdr); +} + +static void mime_param_free(MIME_PARAM *param) +{ +    OPENSSL_free(param->param_name); +    OPENSSL_free(param->param_value); +    OPENSSL_free(param); +} + +/*- + * Check for a multipart boundary. Returns: + * 0 : no boundary + * 1 : part boundary + * 2 : final boundary + */ +static int mime_bound_check(char *line, int linelen, const char *bound, int blen) +{ +    if (linelen == -1) +        linelen = strlen(line); +    if (blen == -1) +        blen = strlen(bound); +    /* Quickly eliminate if line length too short */ +    if (blen + 2 > linelen) +        return 0; +    /* Check for part boundary */ +    if ((strncmp(line, "--", 2) == 0) +        && strncmp(line + 2, bound, blen) == 0) { +        if (strncmp(line + blen + 2, "--", 2) == 0) +            return 2; +        else +            return 1; +    } +    return 0; +} + +static int strip_eol(char *linebuf, int *plen, int flags) +{ +    int len = *plen; +    char *p, c; +    int is_eol = 0; +    p = linebuf + len - 1; +    for (p = linebuf + len - 1; len > 0; len--, p--) { +        c = *p; +        if (c == '\n') +            is_eol = 1; +        else if (is_eol && flags & SMIME_ASCIICRLF && c < 33) +            continue; +        else if (c != '\r') +            break; +    } +    *plen = len; +    return is_eol; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn_moid.c b/openssl-1.1.0h/crypto/asn1/asn_moid.c new file mode 100644 index 0000000..8176b76 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn_moid.c @@ -0,0 +1,105 @@ +/* + * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include <openssl/crypto.h> +#include "internal/cryptlib.h" +#include <openssl/conf.h> +#include <openssl/x509.h> +#include "internal/asn1_int.h" +#include "internal/objects.h" + +/* Simple ASN1 OID module: add all objects in a given section */ + +static int do_create(const char *value, const char *name); + +static int oid_module_init(CONF_IMODULE *md, const CONF *cnf) +{ +    int i; +    const char *oid_section; +    STACK_OF(CONF_VALUE) *sktmp; +    CONF_VALUE *oval; + +    oid_section = CONF_imodule_get_value(md); +    if ((sktmp = NCONF_get_section(cnf, oid_section)) == NULL) { +        ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); +        return 0; +    } +    for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { +        oval = sk_CONF_VALUE_value(sktmp, i); +        if (!do_create(oval->value, oval->name)) { +            ASN1err(ASN1_F_OID_MODULE_INIT, ASN1_R_ADDING_OBJECT); +            return 0; +        } +    } +    return 1; +} + +static void oid_module_finish(CONF_IMODULE *md) +{ +} + +void ASN1_add_oid_module(void) +{ +    CONF_module_add("oid_section", oid_module_init, oid_module_finish); +} + +/*- + * Create an OID based on a name value pair. Accept two formats. + * shortname = 1.2.3.4 + * shortname = some long name, 1.2.3.4 + */ + +static int do_create(const char *value, const char *name) +{ +    int nid; +    ASN1_OBJECT *oid; +    const char *ln, *ostr, *p; +    char *lntmp; +    p = strrchr(value, ','); +    if (!p) { +        ln = name; +        ostr = value; +    } else { +        ln = NULL; +        ostr = p + 1; +        if (!*ostr) +            return 0; +        while (isspace((unsigned char)*ostr)) +            ostr++; +    } + +    nid = OBJ_create(ostr, name, ln); + +    if (nid == NID_undef) +        return 0; + +    if (p) { +        ln = value; +        while (isspace((unsigned char)*ln)) +            ln++; +        p--; +        while (isspace((unsigned char)*p)) { +            if (p == ln) +                return 0; +            p--; +        } +        p++; +        lntmp = OPENSSL_malloc((p - ln) + 1); +        if (lntmp == NULL) +            return 0; +        memcpy(lntmp, ln, p - ln); +        lntmp[p - ln] = 0; +        oid = OBJ_nid2obj(nid); +        oid->ln = lntmp; +    } + +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn_mstbl.c b/openssl-1.1.0h/crypto/asn1/asn_mstbl.c new file mode 100644 index 0000000..8260939 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn_mstbl.c @@ -0,0 +1,114 @@ +/* + * Copyright 2012-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include <openssl/crypto.h> +#include "internal/cryptlib.h" +#include <openssl/conf.h> +#include <openssl/x509v3.h> + +/* Multi string module: add table entries from a given section */ + +static int do_tcreate(const char *value, const char *name); + +static int stbl_module_init(CONF_IMODULE *md, const CONF *cnf) +{ +    int i; +    const char *stbl_section; +    STACK_OF(CONF_VALUE) *sktmp; +    CONF_VALUE *mval; + +    stbl_section = CONF_imodule_get_value(md); +    if ((sktmp = NCONF_get_section(cnf, stbl_section)) == NULL) { +        ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_ERROR_LOADING_SECTION); +        return 0; +    } +    for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { +        mval = sk_CONF_VALUE_value(sktmp, i); +        if (!do_tcreate(mval->value, mval->name)) { +            ASN1err(ASN1_F_STBL_MODULE_INIT, ASN1_R_INVALID_VALUE); +            return 0; +        } +    } +    return 1; +} + +static void stbl_module_finish(CONF_IMODULE *md) +{ +    ASN1_STRING_TABLE_cleanup(); +} + +void ASN1_add_stable_module(void) +{ +    CONF_module_add("stbl_section", stbl_module_init, stbl_module_finish); +} + +/* + * Create an table entry based on a name value pair. format is oid_name = + * n1:v1, n2:v2,... where name is "min", "max", "mask" or "flags". + */ + +static int do_tcreate(const char *value, const char *name) +{ +    char *eptr; +    int nid, i, rv = 0; +    long tbl_min = -1, tbl_max = -1; +    unsigned long tbl_mask = 0, tbl_flags = 0; +    STACK_OF(CONF_VALUE) *lst = NULL; +    CONF_VALUE *cnf = NULL; +    nid = OBJ_sn2nid(name); +    if (nid == NID_undef) +        nid = OBJ_ln2nid(name); +    if (nid == NID_undef) +        goto err; +    lst = X509V3_parse_list(value); +    if (!lst) +        goto err; +    for (i = 0; i < sk_CONF_VALUE_num(lst); i++) { +        cnf = sk_CONF_VALUE_value(lst, i); +        if (strcmp(cnf->name, "min") == 0) { +            tbl_min = strtoul(cnf->value, &eptr, 0); +            if (*eptr) +                goto err; +        } else if (strcmp(cnf->name, "max") == 0) { +            tbl_max = strtoul(cnf->value, &eptr, 0); +            if (*eptr) +                goto err; +        } else if (strcmp(cnf->name, "mask") == 0) { +            if (!ASN1_str2mask(cnf->value, &tbl_mask) || !tbl_mask) +                goto err; +        } else if (strcmp(cnf->name, "flags") == 0) { +            if (strcmp(cnf->value, "nomask") == 0) +                tbl_flags = STABLE_NO_MASK; +            else if (strcmp(cnf->value, "none") == 0) +                tbl_flags = STABLE_FLAGS_CLEAR; +            else +                goto err; +        } else +            goto err; +    } +    rv = 1; + err: +    if (rv == 0) { +        ASN1err(ASN1_F_DO_TCREATE, ASN1_R_INVALID_STRING_TABLE_VALUE); +        if (cnf) +            ERR_add_error_data(4, "field=", cnf->name, +                               ", value=", cnf->value); +        else +            ERR_add_error_data(4, "name=", name, ", value=", value); +    } else { +        rv = ASN1_STRING_TABLE_add(nid, tbl_min, tbl_max, +                                   tbl_mask, tbl_flags); +        if (!rv) +            ASN1err(ASN1_F_DO_TCREATE, ERR_R_MALLOC_FAILURE); +    } +    sk_CONF_VALUE_pop_free(lst, X509V3_conf_free); +    return rv; +} diff --git a/openssl-1.1.0h/crypto/asn1/asn_pack.c b/openssl-1.1.0h/crypto/asn1/asn_pack.c new file mode 100644 index 0000000..63bc306 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/asn_pack.c @@ -0,0 +1,62 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> + +/* ASN1 packing and unpacking functions */ + +ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ +    ASN1_STRING *octmp; + +     if (oct == NULL || *oct == NULL) { +        if ((octmp = ASN1_STRING_new()) == NULL) { +            ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); +            return NULL; +        } +    } else { +        octmp = *oct; +    } + +    OPENSSL_free(octmp->data); +    octmp->data = NULL; + +    if ((octmp->length = ASN1_item_i2d(obj, &octmp->data, it)) == 0) { +        ASN1err(ASN1_F_ASN1_ITEM_PACK, ASN1_R_ENCODE_ERROR); +        goto err; +    } +    if (octmp->data == NULL) { +        ASN1err(ASN1_F_ASN1_ITEM_PACK, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    if (oct != NULL && *oct == NULL) +        *oct = octmp; + +    return octmp; + err: +    if (oct == NULL || *oct == NULL) +        ASN1_STRING_free(octmp); +    return NULL; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_item_unpack(const ASN1_STRING *oct, const ASN1_ITEM *it) +{ +    const unsigned char *p; +    void *ret; + +    p = oct->data; +    if ((ret = ASN1_item_d2i(NULL, &p, oct->length, it)) == NULL) +        ASN1err(ASN1_F_ASN1_ITEM_UNPACK, ASN1_R_DECODE_ERROR); +    return ret; +} diff --git a/openssl-1.1.0h/crypto/asn1/bio_asn1.c b/openssl-1.1.0h/crypto/asn1/bio_asn1.c new file mode 100644 index 0000000..2a8a41f --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/bio_asn1.c @@ -0,0 +1,437 @@ +/* + * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * Experimental ASN1 BIO. When written through the data is converted to an + * ASN1 string type: default is OCTET STRING. Additional functions can be + * provided to add prefix and suffix data. + */ + +#include <string.h> +#include <internal/bio.h> +#include <openssl/asn1.h> + +/* Must be large enough for biggest tag+length */ +#define DEFAULT_ASN1_BUF_SIZE 20 + +typedef enum { +    ASN1_STATE_START, +    ASN1_STATE_PRE_COPY, +    ASN1_STATE_HEADER, +    ASN1_STATE_HEADER_COPY, +    ASN1_STATE_DATA_COPY, +    ASN1_STATE_POST_COPY, +    ASN1_STATE_DONE +} asn1_bio_state_t; + +typedef struct BIO_ASN1_EX_FUNCS_st { +    asn1_ps_func *ex_func; +    asn1_ps_func *ex_free_func; +} BIO_ASN1_EX_FUNCS; + +typedef struct BIO_ASN1_BUF_CTX_t { +    /* Internal state */ +    asn1_bio_state_t state; +    /* Internal buffer */ +    unsigned char *buf; +    /* Size of buffer */ +    int bufsize; +    /* Current position in buffer */ +    int bufpos; +    /* Current buffer length */ +    int buflen; +    /* Amount of data to copy */ +    int copylen; +    /* Class and tag to use */ +    int asn1_class, asn1_tag; +    asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free; +    /* Extra buffer for prefix and suffix data */ +    unsigned char *ex_buf; +    int ex_len; +    int ex_pos; +    void *ex_arg; +} BIO_ASN1_BUF_CTX; + +static int asn1_bio_write(BIO *h, const char *buf, int num); +static int asn1_bio_read(BIO *h, char *buf, int size); +static int asn1_bio_puts(BIO *h, const char *str); +static int asn1_bio_gets(BIO *h, char *str, int size); +static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int asn1_bio_new(BIO *h); +static int asn1_bio_free(BIO *data); +static long asn1_bio_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size); +static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, +                             asn1_ps_func *cleanup, asn1_bio_state_t next); +static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, +                             asn1_ps_func *setup, +                             asn1_bio_state_t ex_state, +                             asn1_bio_state_t other_state); + +static const BIO_METHOD methods_asn1 = { +    BIO_TYPE_ASN1, +    "asn1", +    asn1_bio_write, +    asn1_bio_read, +    asn1_bio_puts, +    asn1_bio_gets, +    asn1_bio_ctrl, +    asn1_bio_new, +    asn1_bio_free, +    asn1_bio_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_asn1(void) +{ +    return (&methods_asn1); +} + +static int asn1_bio_new(BIO *b) +{ +    BIO_ASN1_BUF_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx)); + +    if (ctx == NULL) +        return 0; +    if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE)) { +        OPENSSL_free(ctx); +        return 0; +    } +    BIO_set_data(b, ctx); +    BIO_set_init(b, 1); + +    return 1; +} + +static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size) +{ +    ctx->buf = OPENSSL_malloc(size); +    if (ctx->buf == NULL) +        return 0; +    ctx->bufsize = size; +    ctx->asn1_class = V_ASN1_UNIVERSAL; +    ctx->asn1_tag = V_ASN1_OCTET_STRING; +    ctx->state = ASN1_STATE_START; +    return 1; +} + +static int asn1_bio_free(BIO *b) +{ +    BIO_ASN1_BUF_CTX *ctx; + +    if (b == NULL) +        return 0; + +    ctx = BIO_get_data(b); +    if (ctx == NULL) +        return 0; + +    OPENSSL_free(ctx->buf); +    OPENSSL_free(ctx); +    BIO_set_data(b, NULL); +    BIO_set_init(b, 0); + +    return 1; +} + +static int asn1_bio_write(BIO *b, const char *in, int inl) +{ +    BIO_ASN1_BUF_CTX *ctx; +    int wrmax, wrlen, ret; +    unsigned char *p; +    BIO *next; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); +    if (in == NULL || inl < 0 || ctx == NULL || next == NULL) +        return 0; + +    wrlen = 0; +    ret = -1; + +    for (;;) { +        switch (ctx->state) { + +            /* Setup prefix data, call it */ +        case ASN1_STATE_START: +            if (!asn1_bio_setup_ex(b, ctx, ctx->prefix, +                                   ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER)) +                return 0; +            break; + +            /* Copy any pre data first */ +        case ASN1_STATE_PRE_COPY: + +            ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free, +                                    ASN1_STATE_HEADER); + +            if (ret <= 0) +                goto done; + +            break; + +        case ASN1_STATE_HEADER: +            ctx->buflen = ASN1_object_size(0, inl, ctx->asn1_tag) - inl; +            OPENSSL_assert(ctx->buflen <= ctx->bufsize); +            p = ctx->buf; +            ASN1_put_object(&p, 0, inl, ctx->asn1_tag, ctx->asn1_class); +            ctx->copylen = inl; +            ctx->state = ASN1_STATE_HEADER_COPY; + +            break; + +        case ASN1_STATE_HEADER_COPY: +            ret = BIO_write(next, ctx->buf + ctx->bufpos, ctx->buflen); +            if (ret <= 0) +                goto done; + +            ctx->buflen -= ret; +            if (ctx->buflen) +                ctx->bufpos += ret; +            else { +                ctx->bufpos = 0; +                ctx->state = ASN1_STATE_DATA_COPY; +            } + +            break; + +        case ASN1_STATE_DATA_COPY: + +            if (inl > ctx->copylen) +                wrmax = ctx->copylen; +            else +                wrmax = inl; +            ret = BIO_write(next, in, wrmax); +            if (ret <= 0) +                goto done; +            wrlen += ret; +            ctx->copylen -= ret; +            in += ret; +            inl -= ret; + +            if (ctx->copylen == 0) +                ctx->state = ASN1_STATE_HEADER; + +            if (inl == 0) +                goto done; + +            break; + +        default: +            BIO_clear_retry_flags(b); +            return 0; + +        } + +    } + + done: +    BIO_clear_retry_flags(b); +    BIO_copy_next_retry(b); + +    return (wrlen > 0) ? wrlen : ret; + +} + +static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, +                             asn1_ps_func *cleanup, asn1_bio_state_t next) +{ +    int ret; + +    if (ctx->ex_len <= 0) +        return 1; +    for (;;) { +        ret = BIO_write(BIO_next(b), ctx->ex_buf + ctx->ex_pos, ctx->ex_len); +        if (ret <= 0) +            break; +        ctx->ex_len -= ret; +        if (ctx->ex_len > 0) +            ctx->ex_pos += ret; +        else { +            if (cleanup) +                cleanup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg); +            ctx->state = next; +            ctx->ex_pos = 0; +            break; +        } +    } +    return ret; +} + +static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx, +                             asn1_ps_func *setup, +                             asn1_bio_state_t ex_state, +                             asn1_bio_state_t other_state) +{ +    if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg)) { +        BIO_clear_retry_flags(b); +        return 0; +    } +    if (ctx->ex_len > 0) +        ctx->state = ex_state; +    else +        ctx->state = other_state; +    return 1; +} + +static int asn1_bio_read(BIO *b, char *in, int inl) +{ +    BIO *next = BIO_next(b); +    if (next == NULL) +        return 0; +    return BIO_read(next, in, inl); +} + +static int asn1_bio_puts(BIO *b, const char *str) +{ +    return asn1_bio_write(b, str, strlen(str)); +} + +static int asn1_bio_gets(BIO *b, char *str, int size) +{ +    BIO *next = BIO_next(b); +    if (next == NULL) +        return 0; +    return BIO_gets(next, str, size); +} + +static long asn1_bio_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ +    BIO *next = BIO_next(b); +    if (next == NULL) +        return 0; +    return BIO_callback_ctrl(next, cmd, fp); +} + +static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2) +{ +    BIO_ASN1_BUF_CTX *ctx; +    BIO_ASN1_EX_FUNCS *ex_func; +    long ret = 1; +    BIO *next; + +    ctx = BIO_get_data(b); +    if (ctx == NULL) +        return 0; +    next = BIO_next(b); +    switch (cmd) { + +    case BIO_C_SET_PREFIX: +        ex_func = arg2; +        ctx->prefix = ex_func->ex_func; +        ctx->prefix_free = ex_func->ex_free_func; +        break; + +    case BIO_C_GET_PREFIX: +        ex_func = arg2; +        ex_func->ex_func = ctx->prefix; +        ex_func->ex_free_func = ctx->prefix_free; +        break; + +    case BIO_C_SET_SUFFIX: +        ex_func = arg2; +        ctx->suffix = ex_func->ex_func; +        ctx->suffix_free = ex_func->ex_free_func; +        break; + +    case BIO_C_GET_SUFFIX: +        ex_func = arg2; +        ex_func->ex_func = ctx->suffix; +        ex_func->ex_free_func = ctx->suffix_free; +        break; + +    case BIO_C_SET_EX_ARG: +        ctx->ex_arg = arg2; +        break; + +    case BIO_C_GET_EX_ARG: +        *(void **)arg2 = ctx->ex_arg; +        break; + +    case BIO_CTRL_FLUSH: +        if (next == NULL) +            return 0; + +        /* Call post function if possible */ +        if (ctx->state == ASN1_STATE_HEADER) { +            if (!asn1_bio_setup_ex(b, ctx, ctx->suffix, +                                   ASN1_STATE_POST_COPY, ASN1_STATE_DONE)) +                return 0; +        } + +        if (ctx->state == ASN1_STATE_POST_COPY) { +            ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free, +                                    ASN1_STATE_DONE); +            if (ret <= 0) +                return ret; +        } + +        if (ctx->state == ASN1_STATE_DONE) +            return BIO_ctrl(next, cmd, arg1, arg2); +        else { +            BIO_clear_retry_flags(b); +            return 0; +        } + +    default: +        if (next == NULL) +            return 0; +        return BIO_ctrl(next, cmd, arg1, arg2); + +    } + +    return ret; +} + +static int asn1_bio_set_ex(BIO *b, int cmd, +                           asn1_ps_func *ex_func, asn1_ps_func *ex_free_func) +{ +    BIO_ASN1_EX_FUNCS extmp; +    extmp.ex_func = ex_func; +    extmp.ex_free_func = ex_free_func; +    return BIO_ctrl(b, cmd, 0, &extmp); +} + +static int asn1_bio_get_ex(BIO *b, int cmd, +                           asn1_ps_func **ex_func, +                           asn1_ps_func **ex_free_func) +{ +    BIO_ASN1_EX_FUNCS extmp; +    int ret; +    ret = BIO_ctrl(b, cmd, 0, &extmp); +    if (ret > 0) { +        *ex_func = extmp.ex_func; +        *ex_free_func = extmp.ex_free_func; +    } +    return ret; +} + +int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, +                        asn1_ps_func *prefix_free) +{ +    return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free); +} + +int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, +                        asn1_ps_func **pprefix_free) +{ +    return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free); +} + +int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, +                        asn1_ps_func *suffix_free) +{ +    return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free); +} + +int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, +                        asn1_ps_func **psuffix_free) +{ +    return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free); +} diff --git a/openssl-1.1.0h/crypto/asn1/bio_ndef.c b/openssl-1.1.0h/crypto/asn1/bio_ndef.c new file mode 100644 index 0000000..0f206b2 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/bio_ndef.c @@ -0,0 +1,199 @@ +/* + * Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/bio.h> +#include <openssl/err.h> + +#include <stdio.h> + +/* Experimental NDEF ASN1 BIO support routines */ + +/* + * The usage is quite simple, initialize an ASN1 structure, get a BIO from it + * then any data written through the BIO will end up translated to + * appropriate format on the fly. The data is streamed out and does *not* + * need to be all held in memory at once. When the BIO is flushed the output + * is finalized and any signatures etc written out. The BIO is a 'proper' + * BIO and can handle non blocking I/O correctly. The usage is simple. The + * implementation is *not*... + */ + +/* BIO support data stored in the ASN1 BIO ex_arg */ + +typedef struct ndef_aux_st { +    /* ASN1 structure this BIO refers to */ +    ASN1_VALUE *val; +    const ASN1_ITEM *it; +    /* Top of the BIO chain */ +    BIO *ndef_bio; +    /* Output BIO */ +    BIO *out; +    /* Boundary where content is inserted */ +    unsigned char **boundary; +    /* DER buffer start */ +    unsigned char *derbuf; +} NDEF_SUPPORT; + +static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg); +static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, +                            void *parg); +static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg); +static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, +                            void *parg); + +BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it) +{ +    NDEF_SUPPORT *ndef_aux = NULL; +    BIO *asn_bio = NULL; +    const ASN1_AUX *aux = it->funcs; +    ASN1_STREAM_ARG sarg; + +    if (!aux || !aux->asn1_cb) { +        ASN1err(ASN1_F_BIO_NEW_NDEF, ASN1_R_STREAMING_NOT_SUPPORTED); +        return NULL; +    } +    ndef_aux = OPENSSL_zalloc(sizeof(*ndef_aux)); +    asn_bio = BIO_new(BIO_f_asn1()); +    if (ndef_aux == NULL || asn_bio == NULL) +        goto err; + +    /* ASN1 bio needs to be next to output BIO */ +    out = BIO_push(asn_bio, out); +    if (out == NULL) +        goto err; + +    BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free); +    BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free); + +    /* +     * Now let callback prepends any digest, cipher etc BIOs ASN1 structure +     * needs. +     */ + +    sarg.out = out; +    sarg.ndef_bio = NULL; +    sarg.boundary = NULL; + +    if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0) +        goto err; + +    ndef_aux->val = val; +    ndef_aux->it = it; +    ndef_aux->ndef_bio = sarg.ndef_bio; +    ndef_aux->boundary = sarg.boundary; +    ndef_aux->out = out; + +    BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux); + +    return sarg.ndef_bio; + + err: +    BIO_free(asn_bio); +    OPENSSL_free(ndef_aux); +    return NULL; +} + +static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg) +{ +    NDEF_SUPPORT *ndef_aux; +    unsigned char *p; +    int derlen; + +    if (!parg) +        return 0; + +    ndef_aux = *(NDEF_SUPPORT **)parg; + +    derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); +    p = OPENSSL_malloc(derlen); +    if (p == NULL) +        return 0; + +    ndef_aux->derbuf = p; +    *pbuf = p; +    derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); + +    if (!*ndef_aux->boundary) +        return 0; + +    *plen = *ndef_aux->boundary - *pbuf; + +    return 1; +} + +static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, +                            void *parg) +{ +    NDEF_SUPPORT *ndef_aux; + +    if (!parg) +        return 0; + +    ndef_aux = *(NDEF_SUPPORT **)parg; + +    OPENSSL_free(ndef_aux->derbuf); + +    ndef_aux->derbuf = NULL; +    *pbuf = NULL; +    *plen = 0; +    return 1; +} + +static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, +                            void *parg) +{ +    NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg; +    if (!ndef_prefix_free(b, pbuf, plen, parg)) +        return 0; +    OPENSSL_free(*pndef_aux); +    *pndef_aux = NULL; +    return 1; +} + +static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg) +{ +    NDEF_SUPPORT *ndef_aux; +    unsigned char *p; +    int derlen; +    const ASN1_AUX *aux; +    ASN1_STREAM_ARG sarg; + +    if (!parg) +        return 0; + +    ndef_aux = *(NDEF_SUPPORT **)parg; + +    aux = ndef_aux->it->funcs; + +    /* Finalize structures */ +    sarg.ndef_bio = ndef_aux->ndef_bio; +    sarg.out = ndef_aux->out; +    sarg.boundary = ndef_aux->boundary; +    if (aux->asn1_cb(ASN1_OP_STREAM_POST, +                     &ndef_aux->val, ndef_aux->it, &sarg) <= 0) +        return 0; + +    derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it); +    p = OPENSSL_malloc(derlen); +    if (p == NULL) +        return 0; + +    ndef_aux->derbuf = p; +    *pbuf = p; +    derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it); + +    if (!*ndef_aux->boundary) +        return 0; +    *pbuf = *ndef_aux->boundary; +    *plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf); + +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/build.info b/openssl-1.1.0h/crypto/asn1/build.info new file mode 100644 index 0000000..c1afb71 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/build.info @@ -0,0 +1,16 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ +        a_object.c a_bitstr.c a_utctm.c a_gentm.c a_time.c a_int.c a_octet.c \ +        a_print.c a_type.c a_dup.c a_d2i_fp.c a_i2d_fp.c \ +        a_utf8.c a_sign.c a_digest.c a_verify.c a_mbstr.c a_strex.c \ +        x_algor.c x_val.c x_sig.c x_bignum.c \ +        x_long.c x_int64.c x_info.c x_spki.c nsseq.c \ +        d2i_pu.c d2i_pr.c i2d_pu.c i2d_pr.c\ +        t_pkey.c t_spki.c t_bitst.c \ +        tasn_new.c tasn_fre.c tasn_enc.c tasn_dec.c tasn_utl.c tasn_typ.c \ +        tasn_prn.c tasn_scn.c ameth_lib.c \ +        f_int.c f_string.c n_pkey.c \ +        x_pkey.c bio_asn1.c bio_ndef.c asn_mime.c \ +        asn1_gen.c asn1_par.c asn1_lib.c asn1_err.c a_strnid.c \ +        evp_asn1.c asn_pack.c p5_pbe.c p5_pbev2.c p5_scrypt.c p8_pkey.c \ +        asn_moid.c asn_mstbl.c diff --git a/openssl-1.1.0h/crypto/asn1/charmap.h b/openssl-1.1.0h/crypto/asn1/charmap.h new file mode 100644 index 0000000..2a75925 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/charmap.h @@ -0,0 +1,34 @@ +/* + * WARNING: do not edit! + * Generated by crypto/asn1/charmap.pl + * + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CHARTYPE_HOST_ANY 4096 +#define CHARTYPE_HOST_DOT 8192 +#define CHARTYPE_HOST_HYPHEN 16384 +#define CHARTYPE_HOST_WILD 32768 + +/* + * Mask of various character properties + */ + +static const unsigned short char_type[] = { +    1026,    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, 1040, 1040, 33792,   25,   25, 16400, 8208,   16, +    4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112,   16,    9, +       9,   16,    9,   16,    0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, +    4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, +    4112, 4112, 4112, 4112, 4112, 4112, 4112,    0, 1025,    0,    0,    0, +       0, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, +    4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, 4112, +    4112, 4112, 4112,    0,    0,    0,    0,    2 +}; diff --git a/openssl-1.1.0h/crypto/asn1/charmap.pl b/openssl-1.1.0h/crypto/asn1/charmap.pl new file mode 100644 index 0000000..26ca325 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/charmap.pl @@ -0,0 +1,117 @@ +#! /usr/bin/env perl +# Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License").  You may not use +# this file except in compliance with the License.  You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + +use strict; + +my ($i, @arr); + +# Set up an array with the type of ASCII characters +# Each set bit represents a character property. + +# RFC2253 character properties +my $RFC2253_ESC = 1;	# Character escaped with \ +my $ESC_CTRL	= 2;	# Escaped control character +# These are used with RFC1779 quoting using " +my $NOESC_QUOTE	= 8;	# Not escaped if quoted +my $PSTRING_CHAR = 0x10;	# Valid PrintableString character +my $RFC2253_FIRST_ESC = 0x20; # Escaped with \ if first character +my $RFC2253_LAST_ESC = 0x40;  # Escaped with \ if last character +my $RFC2254_ESC = 0x400;	# Character escaped \XX +my $HOST_ANY = 0x1000;      # Valid hostname character anywhere in label +my $HOST_DOT = 0x2000;  # Dot: hostname label separator +my $HOST_HYPHEN = 0x4000; # Hyphen: not valid at start or end. +my $HOST_WILD = 0x8000; # Wildcard character + +for($i = 0; $i < 128; $i++) { +	# Set the RFC2253 escape characters (control) +	$arr[$i] = 0; +	if(($i < 32) || ($i > 126)) { +		$arr[$i] |= $ESC_CTRL; +	} + +	# Some PrintableString characters +	if(		   ( ( $i >= ord("a")) && ( $i <= ord("z")) ) +			|| (  ( $i >= ord("A")) && ( $i <= ord("Z")) ) +			|| (  ( $i >= ord("0")) && ( $i <= ord("9")) )  ) { +		$arr[$i] |= $PSTRING_CHAR | $HOST_ANY; +	} +} + +# Now setup the rest + +# Remaining RFC2253 escaped characters + +$arr[ord(" ")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC | $RFC2253_LAST_ESC; +$arr[ord("#")] |= $NOESC_QUOTE | $RFC2253_FIRST_ESC; + +$arr[ord(",")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("+")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord("\"")] |= $RFC2253_ESC; +$arr[ord("\\")] |= $RFC2253_ESC; +$arr[ord("<")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(">")] |= $NOESC_QUOTE | $RFC2253_ESC; +$arr[ord(";")] |= $NOESC_QUOTE | $RFC2253_ESC; + +# Remaining RFC2254 characters + +$arr[0] |= $RFC2254_ESC; +$arr[ord("(")] |= $RFC2254_ESC; +$arr[ord(")")] |= $RFC2254_ESC; +$arr[ord("*")] |= $RFC2254_ESC | $HOST_WILD; +$arr[ord("\\")] |= $RFC2254_ESC; + +# Remaining PrintableString characters + +$arr[ord(" ")] |= $PSTRING_CHAR; +$arr[ord("'")] |= $PSTRING_CHAR; +$arr[ord("(")] |= $PSTRING_CHAR; +$arr[ord(")")] |= $PSTRING_CHAR; +$arr[ord("+")] |= $PSTRING_CHAR; +$arr[ord(",")] |= $PSTRING_CHAR; +$arr[ord("-")] |= $PSTRING_CHAR | $HOST_HYPHEN; +$arr[ord(".")] |= $PSTRING_CHAR | $HOST_DOT; +$arr[ord("/")] |= $PSTRING_CHAR; +$arr[ord(":")] |= $PSTRING_CHAR; +$arr[ord("=")] |= $PSTRING_CHAR; +$arr[ord("?")] |= $PSTRING_CHAR; + +# Now generate the C code + +print <<EOF; +/* + * WARNING: do not edit! + * Generated by crypto/asn1/charmap.pl + * + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define CHARTYPE_HOST_ANY $HOST_ANY +#define CHARTYPE_HOST_DOT $HOST_DOT +#define CHARTYPE_HOST_HYPHEN $HOST_HYPHEN +#define CHARTYPE_HOST_WILD $HOST_WILD + +/* + * Mask of various character properties + */ + +static const unsigned short char_type[] = { +EOF + +print "   "; +for($i = 0; $i < 128; $i++) { +	print("\n   ") if($i && (($i % 12) == 0)); +	printf(" %4d", $arr[$i]); +	print(",") if ($i != 127); +} +print("\n};\n"); + diff --git a/openssl-1.1.0h/crypto/asn1/d2i_pr.c b/openssl-1.1.0h/crypto/asn1/d2i_pr.c new file mode 100644 index 0000000..e311b90 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/d2i_pr.c @@ -0,0 +1,125 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/engine.h> +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp, +                         long length) +{ +    EVP_PKEY *ret; +    const unsigned char *p = *pp; + +    if ((a == NULL) || (*a == NULL)) { +        if ((ret = EVP_PKEY_new()) == NULL) { +            ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_EVP_LIB); +            return (NULL); +        } +    } else { +        ret = *a; +#ifndef OPENSSL_NO_ENGINE +        ENGINE_finish(ret->engine); +        ret->engine = NULL; +#endif +    } + +    if (!EVP_PKEY_set_type(ret, type)) { +        ASN1err(ASN1_F_D2I_PRIVATEKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); +        goto err; +    } + +    if (!ret->ameth->old_priv_decode || +        !ret->ameth->old_priv_decode(ret, &p, length)) { +        if (ret->ameth->priv_decode) { +            EVP_PKEY *tmp; +            PKCS8_PRIV_KEY_INFO *p8 = NULL; +            p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); +            if (!p8) +                goto err; +            tmp = EVP_PKCS82PKEY(p8); +            PKCS8_PRIV_KEY_INFO_free(p8); +            if (tmp == NULL) +                goto err; +            EVP_PKEY_free(ret); +            ret = tmp; +        } else { +            ASN1err(ASN1_F_D2I_PRIVATEKEY, ERR_R_ASN1_LIB); +            goto err; +        } +    } +    *pp = p; +    if (a != NULL) +        (*a) = ret; +    return (ret); + err: +    if (a == NULL || *a != ret) +        EVP_PKEY_free(ret); +    return (NULL); +} + +/* + * This works like d2i_PrivateKey() except it automatically works out the + * type + */ + +EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp, +                             long length) +{ +    STACK_OF(ASN1_TYPE) *inkey; +    const unsigned char *p; +    int keytype; +    p = *pp; +    /* +     * Dirty trick: read in the ASN1 data into a STACK_OF(ASN1_TYPE): by +     * analyzing it we can determine the passed structure: this assumes the +     * input is surrounded by an ASN1 SEQUENCE. +     */ +    inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, length); +    p = *pp; +    /* +     * Since we only need to discern "traditional format" RSA and DSA keys we +     * can just count the elements. +     */ +    if (sk_ASN1_TYPE_num(inkey) == 6) +        keytype = EVP_PKEY_DSA; +    else if (sk_ASN1_TYPE_num(inkey) == 4) +        keytype = EVP_PKEY_EC; +    else if (sk_ASN1_TYPE_num(inkey) == 3) { /* This seems to be PKCS8, not +                                              * traditional format */ +        PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, length); +        EVP_PKEY *ret; + +        sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); +        if (!p8) { +            ASN1err(ASN1_F_D2I_AUTOPRIVATEKEY, +                    ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); +            return NULL; +        } +        ret = EVP_PKCS82PKEY(p8); +        PKCS8_PRIV_KEY_INFO_free(p8); +        if (ret == NULL) +            return NULL; +        *pp = p; +        if (a) { +            *a = ret; +        } +        return ret; +    } else +        keytype = EVP_PKEY_RSA; +    sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free); +    return d2i_PrivateKey(keytype, a, pp, length); +} diff --git a/openssl-1.1.0h/crypto/asn1/d2i_pu.c b/openssl-1.1.0h/crypto/asn1/d2i_pu.c new file mode 100644 index 0000000..dfdc1a6 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/d2i_pu.c @@ -0,0 +1,78 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/asn1.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/ec.h> + +#include "internal/evp_int.h" + +EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp, +                        long length) +{ +    EVP_PKEY *ret; + +    if ((a == NULL) || (*a == NULL)) { +        if ((ret = EVP_PKEY_new()) == NULL) { +            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); +            return (NULL); +        } +    } else +        ret = *a; + +    if (!EVP_PKEY_set_type(ret, type)) { +        ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_EVP_LIB); +        goto err; +    } + +    switch (EVP_PKEY_id(ret)) { +#ifndef OPENSSL_NO_RSA +    case EVP_PKEY_RSA: +        if ((ret->pkey.rsa = d2i_RSAPublicKey(NULL, pp, length)) == NULL) { +            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); +            goto err; +        } +        break; +#endif +#ifndef OPENSSL_NO_DSA +    case EVP_PKEY_DSA: +        /* TMP UGLY CAST */ +        if (!d2i_DSAPublicKey(&ret->pkey.dsa, pp, length)) { +            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); +            goto err; +        } +        break; +#endif +#ifndef OPENSSL_NO_EC +    case EVP_PKEY_EC: +        if (!o2i_ECPublicKey(&ret->pkey.ec, pp, length)) { +            ASN1err(ASN1_F_D2I_PUBLICKEY, ERR_R_ASN1_LIB); +            goto err; +        } +        break; +#endif +    default: +        ASN1err(ASN1_F_D2I_PUBLICKEY, ASN1_R_UNKNOWN_PUBLIC_KEY_TYPE); +        goto err; +        /* break; */ +    } +    if (a != NULL) +        (*a) = ret; +    return (ret); + err: +    if (a == NULL || *a != ret) +        EVP_PKEY_free(ret); +    return (NULL); +} diff --git a/openssl-1.1.0h/crypto/asn1/evp_asn1.c b/openssl-1.1.0h/crypto/asn1/evp_asn1.c new file mode 100644 index 0000000..a458367 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/evp_asn1.c @@ -0,0 +1,115 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/asn1t.h> + +int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len) +{ +    ASN1_STRING *os; + +    if ((os = ASN1_OCTET_STRING_new()) == NULL) +        return (0); +    if (!ASN1_OCTET_STRING_set(os, data, len)) { +        ASN1_OCTET_STRING_free(os); +        return 0; +    } +    ASN1_TYPE_set(a, V_ASN1_OCTET_STRING, os); +    return (1); +} + +/* int max_len:  for returned value    */ +int ASN1_TYPE_get_octetstring(const ASN1_TYPE *a, unsigned char *data, int max_len) +{ +    int ret, num; +    const unsigned char *p; + +    if ((a->type != V_ASN1_OCTET_STRING) || (a->value.octet_string == NULL)) { +        ASN1err(ASN1_F_ASN1_TYPE_GET_OCTETSTRING, ASN1_R_DATA_IS_WRONG); +        return (-1); +    } +    p = ASN1_STRING_get0_data(a->value.octet_string); +    ret = ASN1_STRING_length(a->value.octet_string); +    if (ret < max_len) +        num = ret; +    else +        num = max_len; +    memcpy(data, p, num); +    return (ret); +} + +typedef struct { +    long num; +    ASN1_OCTET_STRING *oct; +} asn1_int_oct; + +ASN1_SEQUENCE(asn1_int_oct) = { +        ASN1_SIMPLE(asn1_int_oct, num, LONG), +        ASN1_SIMPLE(asn1_int_oct, oct, ASN1_OCTET_STRING) +} static_ASN1_SEQUENCE_END(asn1_int_oct) + +DECLARE_ASN1_ITEM(asn1_int_oct) + +int ASN1_TYPE_set_int_octetstring(ASN1_TYPE *a, long num, unsigned char *data, +                                  int len) +{ +    asn1_int_oct atmp; +    ASN1_OCTET_STRING oct; + +    atmp.num = num; +    atmp.oct = &oct; +    oct.data = data; +    oct.type = V_ASN1_OCTET_STRING; +    oct.length = len; +    oct.flags = 0; + +    if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(asn1_int_oct), &atmp, &a)) +        return 1; +    return 0; +} + +/* + * we return the actual length... + */ +/* int max_len:  for returned value    */ +int ASN1_TYPE_get_int_octetstring(const ASN1_TYPE *a, long *num, +                                  unsigned char *data, int max_len) +{ +    asn1_int_oct *atmp = NULL; +    int ret = -1, n; + +    if ((a->type != V_ASN1_SEQUENCE) || (a->value.sequence == NULL)) { +        goto err; +    } + +    atmp = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(asn1_int_oct), a); + +    if (atmp == NULL) +        goto err; + +    if (num != NULL) +        *num = atmp->num; + +    ret = ASN1_STRING_length(atmp->oct); +    if (max_len > ret) +        n = ret; +    else +        n = max_len; + +    if (data != NULL) +        memcpy(data, ASN1_STRING_get0_data(atmp->oct), n); +    if (ret == -1) { + err: +        ASN1err(ASN1_F_ASN1_TYPE_GET_INT_OCTETSTRING, ASN1_R_DATA_IS_WRONG); +    } +    M_ASN1_free_of(atmp, asn1_int_oct); +    return ret; +} diff --git a/openssl-1.1.0h/crypto/asn1/f_int.c b/openssl-1.1.0h/crypto/asn1/f_int.c new file mode 100644 index 0000000..ec556c9 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/f_int.c @@ -0,0 +1,167 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/asn1.h> + +int i2a_ASN1_INTEGER(BIO *bp, const ASN1_INTEGER *a) +{ +    int i, n = 0; +    static const char *h = "0123456789ABCDEF"; +    char buf[2]; + +    if (a == NULL) +        return (0); + +    if (a->type & V_ASN1_NEG) { +        if (BIO_write(bp, "-", 1) != 1) +            goto err; +        n = 1; +    } + +    if (a->length == 0) { +        if (BIO_write(bp, "00", 2) != 2) +            goto err; +        n += 2; +    } else { +        for (i = 0; i < a->length; i++) { +            if ((i != 0) && (i % 35 == 0)) { +                if (BIO_write(bp, "\\\n", 2) != 2) +                    goto err; +                n += 2; +            } +            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; +            buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; +            if (BIO_write(bp, buf, 2) != 2) +                goto err; +            n += 2; +        } +    } +    return (n); + err: +    return (-1); +} + +int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size) +{ +    int i, j, k, m, n, again, bufsize; +    unsigned char *s = NULL, *sp; +    unsigned char *bufp; +    int num = 0, slen = 0, first = 1; + +    bs->type = V_ASN1_INTEGER; + +    bufsize = BIO_gets(bp, buf, size); +    for (;;) { +        if (bufsize < 1) +            goto err; +        i = bufsize; +        if (buf[i - 1] == '\n') +            buf[--i] = '\0'; +        if (i == 0) +            goto err; +        if (buf[i - 1] == '\r') +            buf[--i] = '\0'; +        if (i == 0) +            goto err; +        again = (buf[i - 1] == '\\'); + +        for (j = 0; j < i; j++) { +#ifndef CHARSET_EBCDIC +            if (!(((buf[j] >= '0') && (buf[j] <= '9')) || +                  ((buf[j] >= 'a') && (buf[j] <= 'f')) || +                  ((buf[j] >= 'A') && (buf[j] <= 'F')))) +#else +            /* +             * This #ifdef is not strictly necessary, since the characters +             * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but +             * not the whole alphabet). Nevertheless, isxdigit() is faster. +             */ +            if (!isxdigit(buf[j])) +#endif +            { +                i = j; +                break; +            } +        } +        buf[i] = '\0'; +        /* +         * We have now cleared all the crap off the end of the line +         */ +        if (i < 2) +            goto err; + +        bufp = (unsigned char *)buf; +        if (first) { +            first = 0; +            if ((bufp[0] == '0') && (bufp[1] == '0')) { +                bufp += 2; +                i -= 2; +            } +        } +        k = 0; +        i -= again; +        if (i % 2 != 0) { +            ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_ODD_NUMBER_OF_CHARS); +            OPENSSL_free(s); +            return 0; +        } +        i /= 2; +        if (num + i > slen) { +            sp = OPENSSL_clear_realloc(s, slen, num + i * 2); +            if (sp == NULL) { +                ASN1err(ASN1_F_A2I_ASN1_INTEGER, ERR_R_MALLOC_FAILURE); +                OPENSSL_free(s); +                return 0; +            } +            s = sp; +            slen = num + i * 2; +        } +        for (j = 0; j < i; j++, k += 2) { +            for (n = 0; n < 2; n++) { +                m = OPENSSL_hexchar2int(bufp[k + n]); +                if (m < 0) { +                    ASN1err(ASN1_F_A2I_ASN1_INTEGER, +                            ASN1_R_NON_HEX_CHARACTERS); +                    goto err; +                } +                s[num + j] <<= 4; +                s[num + j] |= m; +            } +        } +        num += i; +        if (again) +            bufsize = BIO_gets(bp, buf, size); +        else +            break; +    } +    bs->length = num; +    bs->data = s; +    return 1; + err: +    ASN1err(ASN1_F_A2I_ASN1_INTEGER, ASN1_R_SHORT_LINE); +    OPENSSL_free(s); +    return 0; +} + +int i2a_ASN1_ENUMERATED(BIO *bp, const ASN1_ENUMERATED *a) +{ +    return i2a_ASN1_INTEGER(bp, a); +} + +int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size) +{ +    int rv = a2i_ASN1_INTEGER(bp, bs, buf, size); +    if (rv == 1) +        bs->type = V_ASN1_INTEGER | (bs->type & V_ASN1_NEG); +    return rv; +} diff --git a/openssl-1.1.0h/crypto/asn1/f_string.c b/openssl-1.1.0h/crypto/asn1/f_string.c new file mode 100644 index 0000000..b9258bb --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/f_string.c @@ -0,0 +1,148 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <ctype.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/asn1.h> + +int i2a_ASN1_STRING(BIO *bp, const ASN1_STRING *a, int type) +{ +    int i, n = 0; +    static const char *h = "0123456789ABCDEF"; +    char buf[2]; + +    if (a == NULL) +        return (0); + +    if (a->length == 0) { +        if (BIO_write(bp, "0", 1) != 1) +            goto err; +        n = 1; +    } else { +        for (i = 0; i < a->length; i++) { +            if ((i != 0) && (i % 35 == 0)) { +                if (BIO_write(bp, "\\\n", 2) != 2) +                    goto err; +                n += 2; +            } +            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f]; +            buf[1] = h[((unsigned char)a->data[i]) & 0x0f]; +            if (BIO_write(bp, buf, 2) != 2) +                goto err; +            n += 2; +        } +    } +    return (n); + err: +    return (-1); +} + +int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size) +{ +    int i, j, k, m, n, again, bufsize, spec_char; +    unsigned char *s = NULL, *sp; +    unsigned char *bufp; +    int num = 0, slen = 0, first = 1; + +    bufsize = BIO_gets(bp, buf, size); +    for (;;) { +        if (bufsize < 1) { +            if (first) +                break; +            else +                goto err; +        } +        first = 0; + +        i = bufsize; +        if (buf[i - 1] == '\n') +            buf[--i] = '\0'; +        if (i == 0) +            goto err; +        if (buf[i - 1] == '\r') +            buf[--i] = '\0'; +        if (i == 0) +            goto err; +        again = (buf[i - 1] == '\\'); + +        for (j = i - 1; j > 0; j--) { +#ifndef CHARSET_EBCDIC +            spec_char = (!(((buf[j] >= '0') && (buf[j] <= '9')) || +                  ((buf[j] >= 'a') && (buf[j] <= 'f')) || +                  ((buf[j] >= 'A') && (buf[j] <= 'F')))); +#else +            /* +             * This #ifdef is not strictly necessary, since the characters +             * A...F a...f 0...9 are contiguous (yes, even in EBCDIC - but +             * not the whole alphabet). Nevertheless, isxdigit() is faster. +             */ +            spec_char = (!isxdigit(buf[j])); +#endif +            if (spec_char) { +                i = j; +                break; +            } +        } +        buf[i] = '\0'; +        /* +         * We have now cleared all the crap off the end of the line +         */ +        if (i < 2) +            goto err; + +        bufp = (unsigned char *)buf; + +        k = 0; +        i -= again; +        if (i % 2 != 0) { +            ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_ODD_NUMBER_OF_CHARS); +            OPENSSL_free(s); +            return 0; +        } +        i /= 2; +        if (num + i > slen) { +            sp = OPENSSL_realloc(s, (unsigned int)num + i * 2); +            if (sp == NULL) { +                ASN1err(ASN1_F_A2I_ASN1_STRING, ERR_R_MALLOC_FAILURE); +                OPENSSL_free(s); +                return 0; +            } +            s = sp; +            slen = num + i * 2; +        } +        for (j = 0; j < i; j++, k += 2) { +            for (n = 0; n < 2; n++) { +                m = OPENSSL_hexchar2int(bufp[k + n]); +                if (m < 0) { +                    ASN1err(ASN1_F_A2I_ASN1_STRING, +                            ASN1_R_NON_HEX_CHARACTERS); +                    OPENSSL_free(s); +                    return 0; +                } +                s[num + j] <<= 4; +                s[num + j] |= m; +            } +        } +        num += i; +        if (again) +            bufsize = BIO_gets(bp, buf, size); +        else +            break; +    } +    bs->length = num; +    bs->data = s; +    return 1; + + err: +    ASN1err(ASN1_F_A2I_ASN1_STRING, ASN1_R_SHORT_LINE); +    OPENSSL_free(s); +    return 0; +} diff --git a/openssl-1.1.0h/crypto/asn1/i2d_pr.c b/openssl-1.1.0h/crypto/asn1/i2d_pr.c new file mode 100644 index 0000000..445b0c8 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/i2d_pr.c @@ -0,0 +1,33 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/x509.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +int i2d_PrivateKey(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(a); +        int ret = 0; +        if (p8 != NULL) { +            ret = i2d_PKCS8_PRIV_KEY_INFO(p8, pp); +            PKCS8_PRIV_KEY_INFO_free(p8); +        } +        return ret; +    } +    ASN1err(ASN1_F_I2D_PRIVATEKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); +    return -1; +} diff --git a/openssl-1.1.0h/crypto/asn1/i2d_pu.c b/openssl-1.1.0h/crypto/asn1/i2d_pu.c new file mode 100644 index 0000000..8986c43 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/i2d_pu.c @@ -0,0 +1,38 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/bn.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/ec.h> + +int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp) +{ +    switch (EVP_PKEY_id(a)) { +#ifndef OPENSSL_NO_RSA +    case EVP_PKEY_RSA: +        return i2d_RSAPublicKey(EVP_PKEY_get0_RSA(a), pp); +#endif +#ifndef OPENSSL_NO_DSA +    case EVP_PKEY_DSA: +        return i2d_DSAPublicKey(EVP_PKEY_get0_DSA(a), pp); +#endif +#ifndef OPENSSL_NO_EC +    case EVP_PKEY_EC: +        return i2o_ECPublicKey(EVP_PKEY_get0_EC_KEY(a), pp); +#endif +    default: +        ASN1err(ASN1_F_I2D_PUBLICKEY, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE); +        return -1; +    } +} diff --git a/openssl-1.1.0h/crypto/asn1/n_pkey.c b/openssl-1.1.0h/crypto/asn1/n_pkey.c new file mode 100644 index 0000000..267ce60 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/n_pkey.c @@ -0,0 +1,62 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "openssl/opensslconf.h" +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include "internal/cryptlib.h" +# include <stdio.h> +# include <openssl/rsa.h> +# include <openssl/objects.h> +# include <openssl/asn1t.h> +# include <openssl/evp.h> +# include <openssl/x509.h> + +# ifndef OPENSSL_NO_RC4 + +typedef struct netscape_pkey_st { +    long version; +    X509_ALGOR *algor; +    ASN1_OCTET_STRING *private_key; +} NETSCAPE_PKEY; + +typedef struct netscape_encrypted_pkey_st { +    ASN1_OCTET_STRING *os; +    /* +     * This is the same structure as DigestInfo so use it: although this +     * isn't really anything to do with digests. +     */ +    X509_SIG *enckey; +} NETSCAPE_ENCRYPTED_PKEY; + + +ASN1_BROKEN_SEQUENCE(NETSCAPE_ENCRYPTED_PKEY) = { +        ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, os, ASN1_OCTET_STRING), +        ASN1_SIMPLE(NETSCAPE_ENCRYPTED_PKEY, enckey, X509_SIG) +} static_ASN1_BROKEN_SEQUENCE_END(NETSCAPE_ENCRYPTED_PKEY) + +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY,NETSCAPE_ENCRYPTED_PKEY) +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_ENCRYPTED_PKEY) + +ASN1_SEQUENCE(NETSCAPE_PKEY) = { +        ASN1_SIMPLE(NETSCAPE_PKEY, version, LONG), +        ASN1_SIMPLE(NETSCAPE_PKEY, algor, X509_ALGOR), +        ASN1_SIMPLE(NETSCAPE_PKEY, private_key, ASN1_OCTET_STRING) +} static_ASN1_SEQUENCE_END(NETSCAPE_PKEY) + +DECLARE_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) +DECLARE_ASN1_ENCODE_FUNCTIONS_const(NETSCAPE_PKEY,NETSCAPE_PKEY) +IMPLEMENT_ASN1_FUNCTIONS_const(NETSCAPE_PKEY) + +# endif                         /* OPENSSL_NO_RC4 */ + +#endif diff --git a/openssl-1.1.0h/crypto/asn1/nsseq.c b/openssl-1.1.0h/crypto/asn1/nsseq.c new file mode 100644 index 0000000..c7baf40 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/nsseq.c @@ -0,0 +1,34 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <stdlib.h> +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/objects.h> + +static int nsseq_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, +                    void *exarg) +{ +    if (operation == ASN1_OP_NEW_POST) { +        NETSCAPE_CERT_SEQUENCE *nsseq; +        nsseq = (NETSCAPE_CERT_SEQUENCE *)*pval; +        nsseq->type = OBJ_nid2obj(NID_netscape_cert_sequence); +    } +    return 1; +} + +/* Netscape certificate sequence structure */ + +ASN1_SEQUENCE_cb(NETSCAPE_CERT_SEQUENCE, nsseq_cb) = { +        ASN1_SIMPLE(NETSCAPE_CERT_SEQUENCE, type, ASN1_OBJECT), +        ASN1_EXP_SEQUENCE_OF_OPT(NETSCAPE_CERT_SEQUENCE, certs, X509, 0) +} ASN1_SEQUENCE_END_cb(NETSCAPE_CERT_SEQUENCE, NETSCAPE_CERT_SEQUENCE) + +IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_CERT_SEQUENCE) diff --git a/openssl-1.1.0h/crypto/asn1/p5_pbe.c b/openssl-1.1.0h/crypto/asn1/p5_pbe.c new file mode 100644 index 0000000..ab7e168 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/p5_pbe.c @@ -0,0 +1,96 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/rand.h> + +/* PKCS#5 password based encryption structure */ + +ASN1_SEQUENCE(PBEPARAM) = { +        ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING), +        ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER) +} ASN1_SEQUENCE_END(PBEPARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM) + +/* Set an algorithm identifier for a PKCS#5 PBE algorithm */ + +int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter, +                         const unsigned char *salt, int saltlen) +{ +    PBEPARAM *pbe = NULL; +    ASN1_STRING *pbe_str = NULL; +    unsigned char *sstr = NULL; + +    pbe = PBEPARAM_new(); +    if (pbe == NULL) { +        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    if (iter <= 0) +        iter = PKCS5_DEFAULT_ITER; +    if (!ASN1_INTEGER_set(pbe->iter, iter)) { +        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    if (!saltlen) +        saltlen = PKCS5_SALT_LEN; + +    sstr = OPENSSL_malloc(saltlen); +    if (sstr == NULL) { +        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); +        goto err; +    } +    if (salt) +        memcpy(sstr, salt, saltlen); +    else if (RAND_bytes(sstr, saltlen) <= 0) +        goto err; + +    ASN1_STRING_set0(pbe->salt, sstr, saltlen); +    sstr = NULL; + +    if (!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str)) { +        ASN1err(ASN1_F_PKCS5_PBE_SET0_ALGOR, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    PBEPARAM_free(pbe); +    pbe = NULL; + +    if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str)) +        return 1; + + err: +    OPENSSL_free(sstr); +    PBEPARAM_free(pbe); +    ASN1_STRING_free(pbe_str); +    return 0; +} + +/* Return an algorithm identifier for a PKCS#5 PBE algorithm */ + +X509_ALGOR *PKCS5_pbe_set(int alg, int iter, +                          const unsigned char *salt, int saltlen) +{ +    X509_ALGOR *ret; +    ret = X509_ALGOR_new(); +    if (ret == NULL) { +        ASN1err(ASN1_F_PKCS5_PBE_SET, ERR_R_MALLOC_FAILURE); +        return NULL; +    } + +    if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) +        return ret; + +    X509_ALGOR_free(ret); +    return NULL; +} diff --git a/openssl-1.1.0h/crypto/asn1/p5_pbev2.c b/openssl-1.1.0h/crypto/asn1/p5_pbev2.c new file mode 100644 index 0000000..14e8700 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/p5_pbev2.c @@ -0,0 +1,221 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include <openssl/rand.h> + +/* PKCS#5 v2.0 password based encryption structures */ + +ASN1_SEQUENCE(PBE2PARAM) = { +        ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR), +        ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR) +} ASN1_SEQUENCE_END(PBE2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM) + +ASN1_SEQUENCE(PBKDF2PARAM) = { +        ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY), +        ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER), +        ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER), +        ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR) +} ASN1_SEQUENCE_END(PBKDF2PARAM) + +IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM) + +/* + * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: yes I know + * this is horrible! Extended version to allow application supplied PRF NID + * and IV. + */ + +X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, +                              unsigned char *salt, int saltlen, +                              unsigned char *aiv, int prf_nid) +{ +    X509_ALGOR *scheme = NULL, *ret = NULL; +    int alg_nid, keylen; +    EVP_CIPHER_CTX *ctx = NULL; +    unsigned char iv[EVP_MAX_IV_LENGTH]; +    PBE2PARAM *pbe2 = NULL; + +    alg_nid = EVP_CIPHER_type(cipher); +    if (alg_nid == NID_undef) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, +                ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); +        goto err; +    } + +    if ((pbe2 = PBE2PARAM_new()) == NULL) +        goto merr; + +    /* Setup the AlgorithmIdentifier for the encryption scheme */ +    scheme = pbe2->encryption; +    scheme->algorithm = OBJ_nid2obj(alg_nid); +    if ((scheme->parameter = ASN1_TYPE_new()) == NULL) +        goto merr; + +    /* Create random IV */ +    if (EVP_CIPHER_iv_length(cipher)) { +        if (aiv) +            memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); +        else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) <= 0) +            goto err; +    } + +    ctx = EVP_CIPHER_CTX_new(); +    if (ctx == NULL) +        goto merr; + +    /* Dummy cipherinit to just setup the IV, and PRF */ +    if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0)) +        goto err; +    if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) < 0) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ASN1_R_ERROR_SETTING_CIPHER_PARAMS); +        goto err; +    } +    /* +     * If prf NID unspecified see if cipher has a preference. An error is OK +     * here: just means use default PRF. +     */ +    if ((prf_nid == -1) && +        EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) { +        ERR_clear_error(); +        prf_nid = NID_hmacWithSHA256; +    } +    EVP_CIPHER_CTX_free(ctx); +    ctx = NULL; + +    /* If its RC2 then we'd better setup the key length */ + +    if (alg_nid == NID_rc2_cbc) +        keylen = EVP_CIPHER_key_length(cipher); +    else +        keylen = -1; + +    /* Setup keyfunc */ + +    X509_ALGOR_free(pbe2->keyfunc); + +    pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen); + +    if (!pbe2->keyfunc) +        goto merr; + +    /* Now set up top level AlgorithmIdentifier */ + +    if ((ret = X509_ALGOR_new()) == NULL) +        goto merr; + +    ret->algorithm = OBJ_nid2obj(NID_pbes2); + +    /* Encode PBE2PARAM into parameter */ + +    if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, +                                 &ret->parameter)) +         goto merr; + +    PBE2PARAM_free(pbe2); +    pbe2 = NULL; + +    return ret; + + merr: +    ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, ERR_R_MALLOC_FAILURE); + + err: +    EVP_CIPHER_CTX_free(ctx); +    PBE2PARAM_free(pbe2); +    /* Note 'scheme' is freed as part of pbe2 */ +    X509_ALGOR_free(ret); + +    return NULL; +} + +X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, +                           unsigned char *salt, int saltlen) +{ +    return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1); +} + +X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen, +                             int prf_nid, int keylen) +{ +    X509_ALGOR *keyfunc = NULL; +    PBKDF2PARAM *kdf = NULL; +    ASN1_OCTET_STRING *osalt = NULL; + +    if ((kdf = PBKDF2PARAM_new()) == NULL) +        goto merr; +    if ((osalt = ASN1_OCTET_STRING_new()) == NULL) +        goto merr; + +    kdf->salt->value.octet_string = osalt; +    kdf->salt->type = V_ASN1_OCTET_STRING; + +    if (saltlen == 0) +        saltlen = PKCS5_SALT_LEN; +    if ((osalt->data = OPENSSL_malloc(saltlen)) == NULL) +        goto merr; + +    osalt->length = saltlen; + +    if (salt) +        memcpy(osalt->data, salt, saltlen); +    else if (RAND_bytes(osalt->data, saltlen) <= 0) +        goto merr; + +    if (iter <= 0) +        iter = PKCS5_DEFAULT_ITER; + +    if (!ASN1_INTEGER_set(kdf->iter, iter)) +        goto merr; + +    /* If have a key len set it up */ + +    if (keylen > 0) { +        if ((kdf->keylength = ASN1_INTEGER_new()) == NULL) +            goto merr; +        if (!ASN1_INTEGER_set(kdf->keylength, keylen)) +            goto merr; +    } + +    /* prf can stay NULL if we are using hmacWithSHA1 */ +    if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1) { +        kdf->prf = X509_ALGOR_new(); +        if (kdf->prf == NULL) +            goto merr; +        X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), V_ASN1_NULL, NULL); +    } + +    /* Finally setup the keyfunc structure */ + +    keyfunc = X509_ALGOR_new(); +    if (keyfunc == NULL) +        goto merr; + +    keyfunc->algorithm = OBJ_nid2obj(NID_id_pbkdf2); + +    /* Encode PBKDF2PARAM into parameter of pbe2 */ + +    if (!ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), kdf, +                                 &keyfunc->parameter)) +         goto merr; + +    PBKDF2PARAM_free(kdf); +    return keyfunc; + + merr: +    ASN1err(ASN1_F_PKCS5_PBKDF2_SET, ERR_R_MALLOC_FAILURE); +    PBKDF2PARAM_free(kdf); +    X509_ALGOR_free(keyfunc); +    return NULL; +} diff --git a/openssl-1.1.0h/crypto/asn1/p5_scrypt.c b/openssl-1.1.0h/crypto/asn1/p5_scrypt.c new file mode 100644 index 0000000..4cb7837 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/p5_scrypt.c @@ -0,0 +1,283 @@ +/* + * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/err.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/rand.h> + +#ifndef OPENSSL_NO_SCRYPT +/* PKCS#5 scrypt password based encryption structures */ + +typedef struct { +    ASN1_OCTET_STRING *salt; +    ASN1_INTEGER *costParameter; +    ASN1_INTEGER *blockSize; +    ASN1_INTEGER *parallelizationParameter; +    ASN1_INTEGER *keyLength; +} SCRYPT_PARAMS; + +ASN1_SEQUENCE(SCRYPT_PARAMS) = { +        ASN1_SIMPLE(SCRYPT_PARAMS, salt, ASN1_OCTET_STRING), +        ASN1_SIMPLE(SCRYPT_PARAMS, costParameter, ASN1_INTEGER), +        ASN1_SIMPLE(SCRYPT_PARAMS, blockSize, ASN1_INTEGER), +        ASN1_SIMPLE(SCRYPT_PARAMS, parallelizationParameter, ASN1_INTEGER), +        ASN1_OPT(SCRYPT_PARAMS, keyLength, ASN1_INTEGER), +} static_ASN1_SEQUENCE_END(SCRYPT_PARAMS) + +DECLARE_ASN1_ALLOC_FUNCTIONS(SCRYPT_PARAMS) +IMPLEMENT_ASN1_ALLOC_FUNCTIONS(SCRYPT_PARAMS) + +static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen, +                                    size_t keylen, uint64_t N, uint64_t r, +                                    uint64_t p); + +/* + * Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm using scrypt + */ + +X509_ALGOR *PKCS5_pbe2_set_scrypt(const EVP_CIPHER *cipher, +                                  const unsigned char *salt, int saltlen, +                                  unsigned char *aiv, uint64_t N, uint64_t r, +                                  uint64_t p) +{ +    X509_ALGOR *scheme = NULL, *ret = NULL; +    int alg_nid; +    size_t keylen = 0; +    EVP_CIPHER_CTX *ctx = NULL; +    unsigned char iv[EVP_MAX_IV_LENGTH]; +    PBE2PARAM *pbe2 = NULL; + +    if (!cipher) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_PASSED_NULL_PARAMETER); +        goto err; +    } + +    if (EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, +                ASN1_R_INVALID_SCRYPT_PARAMETERS); +        goto err; +    } + +    alg_nid = EVP_CIPHER_type(cipher); +    if (alg_nid == NID_undef) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, +                ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); +        goto err; +    } + +    pbe2 = PBE2PARAM_new(); +    if (pbe2 == NULL) +        goto merr; + +    /* Setup the AlgorithmIdentifier for the encryption scheme */ +    scheme = pbe2->encryption; + +    scheme->algorithm = OBJ_nid2obj(alg_nid); +    scheme->parameter = ASN1_TYPE_new(); +    if (scheme->parameter == NULL) +        goto merr; + +    /* Create random IV */ +    if (EVP_CIPHER_iv_length(cipher)) { +        if (aiv) +            memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); +        else if (RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) +            goto err; +    } + +    ctx = EVP_CIPHER_CTX_new(); +    if (ctx == NULL) +        goto merr; + +    /* Dummy cipherinit to just setup the IV */ +    if (EVP_CipherInit_ex(ctx, cipher, NULL, NULL, iv, 0) == 0) +        goto err; +    if (EVP_CIPHER_param_to_asn1(ctx, scheme->parameter) < 0) { +        ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, +                ASN1_R_ERROR_SETTING_CIPHER_PARAMS); +        goto err; +    } +    EVP_CIPHER_CTX_free(ctx); +    ctx = NULL; + +    /* If its RC2 then we'd better setup the key length */ + +    if (alg_nid == NID_rc2_cbc) +        keylen = EVP_CIPHER_key_length(cipher); + +    /* Setup keyfunc */ + +    X509_ALGOR_free(pbe2->keyfunc); + +    pbe2->keyfunc = pkcs5_scrypt_set(salt, saltlen, keylen, N, r, p); + +    if (pbe2->keyfunc == NULL) +        goto merr; + +    /* Now set up top level AlgorithmIdentifier */ + +    ret = X509_ALGOR_new(); +    if (ret == NULL) +        goto merr; + +    ret->algorithm = OBJ_nid2obj(NID_pbes2); + +    /* Encode PBE2PARAM into parameter */ + +    if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(PBE2PARAM), pbe2, +                                &ret->parameter) == NULL) +        goto merr; + +    PBE2PARAM_free(pbe2); +    pbe2 = NULL; + +    return ret; + + merr: +    ASN1err(ASN1_F_PKCS5_PBE2_SET_SCRYPT, ERR_R_MALLOC_FAILURE); + + err: +    PBE2PARAM_free(pbe2); +    X509_ALGOR_free(ret); +    EVP_CIPHER_CTX_free(ctx); + +    return NULL; +} + +static X509_ALGOR *pkcs5_scrypt_set(const unsigned char *salt, size_t saltlen, +                                    size_t keylen, uint64_t N, uint64_t r, +                                    uint64_t p) +{ +    X509_ALGOR *keyfunc = NULL; +    SCRYPT_PARAMS *sparam = SCRYPT_PARAMS_new(); + +    if (sparam == NULL) +        goto merr; + +    if (!saltlen) +        saltlen = PKCS5_SALT_LEN; + +    /* This will either copy salt or grow the buffer */ +    if (ASN1_STRING_set(sparam->salt, salt, saltlen) == 0) +        goto merr; + +    if (salt == NULL && RAND_bytes(sparam->salt->data, saltlen) <= 0) +        goto err; + +    if (ASN1_INTEGER_set_uint64(sparam->costParameter, N) == 0) +        goto merr; + +    if (ASN1_INTEGER_set_uint64(sparam->blockSize, r) == 0) +        goto merr; + +    if (ASN1_INTEGER_set_uint64(sparam->parallelizationParameter, p) == 0) +        goto merr; + +    /* If have a key len set it up */ + +    if (keylen > 0) { +        sparam->keyLength = ASN1_INTEGER_new(); +        if (sparam->keyLength == NULL) +            goto merr; +        if (ASN1_INTEGER_set_int64(sparam->keyLength, keylen) == 0) +            goto merr; +    } + +    /* Finally setup the keyfunc structure */ + +    keyfunc = X509_ALGOR_new(); +    if (keyfunc == NULL) +        goto merr; + +    keyfunc->algorithm = OBJ_nid2obj(NID_id_scrypt); + +    /* Encode SCRYPT_PARAMS into parameter of pbe2 */ + +    if (ASN1_TYPE_pack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), sparam, +                                &keyfunc->parameter) == NULL) +        goto merr; + +    SCRYPT_PARAMS_free(sparam); +    return keyfunc; + + merr: +    ASN1err(ASN1_F_PKCS5_SCRYPT_SET, ERR_R_MALLOC_FAILURE); + err: +    SCRYPT_PARAMS_free(sparam); +    X509_ALGOR_free(keyfunc); +    return NULL; +} + +int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, +                             int passlen, ASN1_TYPE *param, +                             const EVP_CIPHER *c, const EVP_MD *md, int en_de) +{ +    unsigned char *salt, key[EVP_MAX_KEY_LENGTH]; +    uint64_t p, r, N; +    size_t saltlen; +    size_t keylen = 0; +    int rv = 0; +    SCRYPT_PARAMS *sparam = NULL; + +    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { +        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_NO_CIPHER_SET); +        goto err; +    } + +    /* Decode parameter */ + +    sparam = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(SCRYPT_PARAMS), param); + +    if (sparam == NULL) { +        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, EVP_R_DECODE_ERROR); +        goto err; +    } + +    keylen = EVP_CIPHER_CTX_key_length(ctx); + +    /* Now check the parameters of sparam */ + +    if (sparam->keyLength) { +        uint64_t spkeylen; +        if ((ASN1_INTEGER_get_uint64(&spkeylen, sparam->keyLength) == 0) +            || (spkeylen != keylen)) { +            EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, +                   EVP_R_UNSUPPORTED_KEYLENGTH); +            goto err; +        } +    } +    /* Check all parameters fit in uint64_t and are acceptable to scrypt */ +    if (ASN1_INTEGER_get_uint64(&N, sparam->costParameter) == 0 +        || ASN1_INTEGER_get_uint64(&r, sparam->blockSize) == 0 +        || ASN1_INTEGER_get_uint64(&p, sparam->parallelizationParameter) == 0 +        || EVP_PBE_scrypt(NULL, 0, NULL, 0, N, r, p, 0, NULL, 0) == 0) { +        EVPerr(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN, +               EVP_R_ILLEGAL_SCRYPT_PARAMETERS); +        goto err; +    } + +    /* it seems that its all OK */ + +    salt = sparam->salt->data; +    saltlen = sparam->salt->length; +    if (EVP_PBE_scrypt(pass, passlen, salt, saltlen, N, r, p, 0, key, keylen) +        == 0) +        goto err; +    rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); + err: +    if (keylen) +        OPENSSL_cleanse(key, keylen); +    SCRYPT_PARAMS_free(sparam); +    return rv; +} +#endif /* OPENSSL_NO_SCRYPT */ diff --git a/openssl-1.1.0h/crypto/asn1/p8_pkey.c b/openssl-1.1.0h/crypto/asn1/p8_pkey.c new file mode 100644 index 0000000..dbee827 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/p8_pkey.c @@ -0,0 +1,80 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.h" + +/* Minor tweak to operation: zero private key data */ +static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, +                   void *exarg) +{ +    /* Since the structure must still be valid use ASN1_OP_FREE_PRE */ +    if (operation == ASN1_OP_FREE_PRE) { +        PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval; +        if (key->pkey) +            OPENSSL_cleanse(key->pkey->data, key->pkey->length); +    } +    return 1; +} + +ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = { +        ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER), +        ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR), +        ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_OCTET_STRING), +        ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0) +} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO) + +IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO) + +int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, +                    int version, +                    int ptype, void *pval, unsigned char *penc, int penclen) +{ +    if (version >= 0) { +        if (!ASN1_INTEGER_set(priv->version, version)) +            return 0; +    } +    if (!X509_ALGOR_set0(priv->pkeyalg, aobj, ptype, pval)) +        return 0; +    if (penc) +        ASN1_STRING_set0(priv->pkey, penc, penclen); +    return 1; +} + +int PKCS8_pkey_get0(const ASN1_OBJECT **ppkalg, +                    const unsigned char **pk, int *ppklen, +                    const X509_ALGOR **pa, const PKCS8_PRIV_KEY_INFO *p8) +{ +    if (ppkalg) +        *ppkalg = p8->pkeyalg->algorithm; +    if (pk) { +        *pk = ASN1_STRING_get0_data(p8->pkey); +        *ppklen = ASN1_STRING_length(p8->pkey); +    } +    if (pa) +        *pa = p8->pkeyalg; +    return 1; +} + +const STACK_OF(X509_ATTRIBUTE) * +PKCS8_pkey_get0_attrs(const PKCS8_PRIV_KEY_INFO *p8) +{ +    return p8->attributes; +} + +int PKCS8_pkey_add1_attr_by_NID(PKCS8_PRIV_KEY_INFO *p8, int nid, int type, +                                const unsigned char *bytes, int len) +{ +    if (X509at_add1_attr_by_NID(&p8->attributes, nid, type, bytes, len) != NULL) +        return 1; +    return 0; +} diff --git a/openssl-1.1.0h/crypto/asn1/t_bitst.c b/openssl-1.1.0h/crypto/asn1/t_bitst.c new file mode 100644 index 0000000..c0aeca4 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/t_bitst.c @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/conf.h> +#include <openssl/x509v3.h> + +int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs, +                               BIT_STRING_BITNAME *tbl, int indent) +{ +    BIT_STRING_BITNAME *bnam; +    char first = 1; +    BIO_printf(out, "%*s", indent, ""); +    for (bnam = tbl; bnam->lname; bnam++) { +        if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) { +            if (!first) +                BIO_puts(out, ", "); +            BIO_puts(out, bnam->lname); +            first = 0; +        } +    } +    BIO_puts(out, "\n"); +    return 1; +} + +int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, const char *name, int value, +                            BIT_STRING_BITNAME *tbl) +{ +    int bitnum; +    bitnum = ASN1_BIT_STRING_num_asc(name, tbl); +    if (bitnum < 0) +        return 0; +    if (bs) { +        if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value)) +            return 0; +    } +    return 1; +} + +int ASN1_BIT_STRING_num_asc(const char *name, BIT_STRING_BITNAME *tbl) +{ +    BIT_STRING_BITNAME *bnam; +    for (bnam = tbl; bnam->lname; bnam++) { +        if ((strcmp(bnam->sname, name) == 0) +            || (strcmp(bnam->lname, name) == 0)) +            return bnam->bitnum; +    } +    return -1; +} diff --git a/openssl-1.1.0h/crypto/asn1/t_pkey.c b/openssl-1.1.0h/crypto/asn1/t_pkey.c new file mode 100644 index 0000000..3b2c9df --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/t_pkey.c @@ -0,0 +1,93 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include "internal/bn_int.h" + +/* Number of octets per line */ +#define ASN1_BUF_PRINT_WIDTH    15 +/* Maximum indent */ +#define ASN1_PRINT_MAX_INDENT 128 + +int ASN1_buf_print(BIO *bp, const unsigned char *buf, size_t buflen, int indent) +{ +    size_t i; + +    for (i = 0; i < buflen; i++) { +        if ((i % ASN1_BUF_PRINT_WIDTH) == 0) { +            if (i > 0 && BIO_puts(bp, "\n") <= 0) +                return 0; +            if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT)) +                return 0; +        } +        /* +         * Use colon separators for each octet for compatibility as +         * this function is used to print out key components. +         */ +        if (BIO_printf(bp, "%02x%s", buf[i], +                       (i == buflen - 1) ? "" : ":") <= 0) +                return 0; +    } +    if (BIO_write(bp, "\n", 1) <= 0) +        return 0; +    return 1; +} + +int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, +                  unsigned char *ign, int indent) +{ +    int n, rv = 0; +    const char *neg; +    unsigned char *buf = NULL, *tmp = NULL; +    int buflen; + +    if (num == NULL) +        return 1; +    neg = BN_is_negative(num) ? "-" : ""; +    if (!BIO_indent(bp, indent, ASN1_PRINT_MAX_INDENT)) +        return 0; +    if (BN_is_zero(num)) { +        if (BIO_printf(bp, "%s 0\n", number) <= 0) +            return 0; +        return 1; +    } + +    if (BN_num_bytes(num) <= BN_BYTES) { +        if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg, +                       (unsigned long)bn_get_words(num)[0], neg, +                       (unsigned long)bn_get_words(num)[0]) <= 0) +            return 0; +        return 1; +    } + +    buflen = BN_num_bytes(num) + 1; +    buf = tmp = OPENSSL_malloc(buflen); +    if (buf == NULL) +        goto err; +    buf[0] = 0; +    if (BIO_printf(bp, "%s%s\n", number, +                   (neg[0] == '-') ? " (Negative)" : "") <= 0) +        goto err; +    n = BN_bn2bin(num, buf + 1); + +    if (buf[1] & 0x80) +        n++; +    else +        tmp++; + +    if (ASN1_buf_print(bp, tmp, n, indent + 4) == 0) +        goto err; +    rv = 1; +    err: +    OPENSSL_clear_free(buf, buflen); +    return rv; +} diff --git a/openssl-1.1.0h/crypto/asn1/t_spki.c b/openssl-1.1.0h/crypto/asn1/t_spki.c new file mode 100644 index 0000000..51b56d0 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/t_spki.c @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/bn.h> + +/* Print out an SPKI */ + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) +{ +    EVP_PKEY *pkey; +    ASN1_IA5STRING *chal; +    ASN1_OBJECT *spkioid; +    int i, n; +    char *s; +    BIO_printf(out, "Netscape SPKI:\n"); +    X509_PUBKEY_get0_param(&spkioid, NULL, NULL, NULL, spki->spkac->pubkey); +    i = OBJ_obj2nid(spkioid); +    BIO_printf(out, "  Public Key Algorithm: %s\n", +               (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); +    pkey = X509_PUBKEY_get(spki->spkac->pubkey); +    if (!pkey) +        BIO_printf(out, "  Unable to load public key\n"); +    else { +        EVP_PKEY_print_public(out, pkey, 4, NULL); +        EVP_PKEY_free(pkey); +    } +    chal = spki->spkac->challenge; +    if (chal->length) +        BIO_printf(out, "  Challenge String: %s\n", chal->data); +    i = OBJ_obj2nid(spki->sig_algor.algorithm); +    BIO_printf(out, "  Signature Algorithm: %s", +               (i == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(i)); + +    n = spki->signature->length; +    s = (char *)spki->signature->data; +    for (i = 0; i < n; i++) { +        if ((i % 18) == 0) +            BIO_write(out, "\n      ", 7); +        BIO_printf(out, "%02x%s", (unsigned char)s[i], +                   ((i + 1) == n) ? "" : ":"); +    } +    BIO_write(out, "\n", 1); +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_dec.c b/openssl-1.1.0h/crypto/asn1/tasn_dec.c new file mode 100644 index 0000000..af8641e --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_dec.c @@ -0,0 +1,1159 @@ +/* + * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <string.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/err.h> +#include "internal/numbers.h" +#include "asn1_locl.h" + +/* + * Constructed types with a recursive definition (such as can be found in PKCS7) + * could eventually exceed the stack given malicious input with excessive + * recursion. Therefore we limit the stack depth. This is the maximum number of + * recursive invocations of asn1_item_embed_d2i(). + */ +#define ASN1_MAX_CONSTRUCTED_NEST 30 + +static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, +                               long len, const ASN1_ITEM *it, +                               int tag, int aclass, char opt, ASN1_TLC *ctx, +                               int depth); + +static int asn1_check_eoc(const unsigned char **in, long len); +static int asn1_find_end(const unsigned char **in, long len, char inf); + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, +                        char inf, int tag, int aclass, int depth); + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen); + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, +                           char *inf, char *cst, +                           const unsigned char **in, long len, +                           int exptag, int expclass, char opt, ASN1_TLC *ctx); + +static int asn1_template_ex_d2i(ASN1_VALUE **pval, +                                const unsigned char **in, long len, +                                const ASN1_TEMPLATE *tt, char opt, +                                ASN1_TLC *ctx, int depth); +static int asn1_template_noexp_d2i(ASN1_VALUE **val, +                                   const unsigned char **in, long len, +                                   const ASN1_TEMPLATE *tt, char opt, +                                   ASN1_TLC *ctx, int depth); +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, +                                 const unsigned char **in, long len, +                                 const ASN1_ITEM *it, +                                 int tag, int aclass, char opt, +                                 ASN1_TLC *ctx); +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                       int utype, char *free_cont, const ASN1_ITEM *it); + +/* Table to convert tags to bit values, used for MSTRING type */ +static const unsigned long tag2bit[32] = { +    /* tags  0 -  3 */ +    0, 0, 0, B_ASN1_BIT_STRING, +    /* tags  4- 7 */ +    B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, +    /* tags  8-11 */ +    B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, +    /* tags 12-15 */ +    B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, +    /* tags 16-19 */ +    B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, +    /* tags 20-22 */ +    B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, +    /* tags 23-24 */ +    B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, +    /* tags 25-27 */ +    B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, +    /* tags 28-31 */ +    B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, +}; + +unsigned long ASN1_tag2bit(int tag) +{ +    if ((tag < 0) || (tag > 30)) +        return 0; +    return tag2bit[tag]; +} + +/* Macro to initialize and invalidate the cache */ + +#define asn1_tlc_clear(c)       if (c) (c)->valid = 0 +/* Version to avoid compiler warning about 'c' always non-NULL */ +#define asn1_tlc_clear_nc(c)    (c)->valid = 0 + +/* + * Decode an ASN1 item, this currently behaves just like a standard 'd2i' + * function. 'in' points to a buffer to read the data from, in future we + * will have more advanced versions that can input data a piece at a time and + * this will simply be a special case. + */ + +ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval, +                          const unsigned char **in, long len, +                          const ASN1_ITEM *it) +{ +    ASN1_TLC c; +    ASN1_VALUE *ptmpval = NULL; +    if (!pval) +        pval = &ptmpval; +    asn1_tlc_clear_nc(&c); +    if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) +        return *pval; +    return NULL; +} + +int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len, +                     const ASN1_ITEM *it, +                     int tag, int aclass, char opt, ASN1_TLC *ctx) +{ +    int rv; +    rv = asn1_item_embed_d2i(pval, in, len, it, tag, aclass, opt, ctx, 0); +    if (rv <= 0) +        ASN1_item_ex_free(pval, it); +    return rv; +} + +/* + * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and + * tag mismatch return -1 to handle OPTIONAL + */ + +static int asn1_item_embed_d2i(ASN1_VALUE **pval, const unsigned char **in, +                               long len, const ASN1_ITEM *it, +                               int tag, int aclass, char opt, ASN1_TLC *ctx, +                               int depth) +{ +    const ASN1_TEMPLATE *tt, *errtt = NULL; +    const ASN1_EXTERN_FUNCS *ef; +    const ASN1_AUX *aux = it->funcs; +    ASN1_aux_cb *asn1_cb; +    const unsigned char *p = NULL, *q; +    unsigned char oclass; +    char seq_eoc, seq_nolen, cst, isopt; +    long tmplen; +    int i; +    int otag; +    int ret = 0; +    ASN1_VALUE **pchptr; +    if (!pval) +        return 0; +    if (aux && aux->asn1_cb) +        asn1_cb = aux->asn1_cb; +    else +        asn1_cb = 0; + +    if (++depth > ASN1_MAX_CONSTRUCTED_NEST) { +        ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NESTED_TOO_DEEP); +        goto err; +    } + +    switch (it->itype) { +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) { +            /* +             * tagging or OPTIONAL is currently illegal on an item template +             * because the flags can't get passed down. In practice this +             * isn't a problem: we include the relevant flags from the item +             * template in the template itself. +             */ +            if ((tag != -1) || opt) { +                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, +                        ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE); +                goto err; +            } +            return asn1_template_ex_d2i(pval, in, len, +                                        it->templates, opt, ctx, depth); +        } +        return asn1_d2i_ex_primitive(pval, in, len, it, +                                     tag, aclass, opt, ctx); + +    case ASN1_ITYPE_MSTRING: +        p = *in; +        /* Just read in tag and class */ +        ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL, +                              &p, len, -1, 0, 1, ctx); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } + +        /* Must be UNIVERSAL class */ +        if (oclass != V_ASN1_UNIVERSAL) { +            /* If OPTIONAL, assume this is OK */ +            if (opt) +                return -1; +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_NOT_UNIVERSAL); +            goto err; +        } +        /* Check tag matches bit map */ +        if (!(ASN1_tag2bit(otag) & it->utype)) { +            /* If OPTIONAL, assume this is OK */ +            if (opt) +                return -1; +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MSTRING_WRONG_TAG); +            goto err; +        } +        return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx); + +    case ASN1_ITYPE_EXTERN: +        /* Use new style d2i */ +        ef = it->funcs; +        return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx); + +    case ASN1_ITYPE_CHOICE: +        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) +            goto auxerr; +        if (*pval) { +            /* Free up and zero CHOICE value if initialised */ +            i = asn1_get_choice_selector(pval, it); +            if ((i >= 0) && (i < it->tcount)) { +                tt = it->templates + i; +                pchptr = asn1_get_field_ptr(pval, tt); +                asn1_template_free(pchptr, tt); +                asn1_set_choice_selector(pval, -1, it); +            } +        } else if (!ASN1_item_ex_new(pval, it)) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } +        /* CHOICE type, try each possibility in turn */ +        p = *in; +        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { +            pchptr = asn1_get_field_ptr(pval, tt); +            /* +             * We mark field as OPTIONAL so its absence can be recognised. +             */ +            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx, depth); +            /* If field not present, try the next one */ +            if (ret == -1) +                continue; +            /* If positive return, read OK, break loop */ +            if (ret > 0) +                break; +            /* +             * Must be an ASN1 parsing error. +             * Free up any partial choice value +             */ +            asn1_template_free(pchptr, tt); +            errtt = tt; +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } + +        /* Did we fall off the end without reading anything? */ +        if (i == it->tcount) { +            /* If OPTIONAL, this is OK */ +            if (opt) { +                /* Free and zero it */ +                ASN1_item_ex_free(pval, it); +                return -1; +            } +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_NO_MATCHING_CHOICE_TYPE); +            goto err; +        } + +        asn1_set_choice_selector(pval, i, it); + +        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) +            goto auxerr; +        *in = p; +        return 1; + +    case ASN1_ITYPE_NDEF_SEQUENCE: +    case ASN1_ITYPE_SEQUENCE: +        p = *in; +        tmplen = len; + +        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ +        if (tag == -1) { +            tag = V_ASN1_SEQUENCE; +            aclass = V_ASN1_UNIVERSAL; +        } +        /* Get SEQUENCE length and update len, p */ +        ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst, +                              &p, len, tag, aclass, opt, ctx); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } else if (ret == -1) +            return -1; +        if (aux && (aux->flags & ASN1_AFLG_BROKEN)) { +            len = tmplen - (p - *in); +            seq_nolen = 1; +        } +        /* If indefinite we don't do a length check */ +        else +            seq_nolen = seq_eoc; +        if (!cst) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_NOT_CONSTRUCTED); +            goto err; +        } + +        if (!*pval && !ASN1_item_ex_new(pval, it)) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } + +        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL)) +            goto auxerr; + +        /* Free up and zero any ADB found */ +        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { +            if (tt->flags & ASN1_TFLG_ADB_MASK) { +                const ASN1_TEMPLATE *seqtt; +                ASN1_VALUE **pseqval; +                seqtt = asn1_do_adb(pval, tt, 0); +                if (seqtt == NULL) +                    continue; +                pseqval = asn1_get_field_ptr(pval, seqtt); +                asn1_template_free(pseqval, seqtt); +            } +        } + +        /* Get each field entry */ +        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { +            const ASN1_TEMPLATE *seqtt; +            ASN1_VALUE **pseqval; +            seqtt = asn1_do_adb(pval, tt, 1); +            if (seqtt == NULL) +                goto err; +            pseqval = asn1_get_field_ptr(pval, seqtt); +            /* Have we ran out of data? */ +            if (!len) +                break; +            q = p; +            if (asn1_check_eoc(&p, len)) { +                if (!seq_eoc) { +                    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_UNEXPECTED_EOC); +                    goto err; +                } +                len -= p - q; +                seq_eoc = 0; +                q = p; +                break; +            } +            /* +             * This determines the OPTIONAL flag value. The field cannot be +             * omitted if it is the last of a SEQUENCE and there is still +             * data to be read. This isn't strictly necessary but it +             * increases efficiency in some cases. +             */ +            if (i == (it->tcount - 1)) +                isopt = 0; +            else +                isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL); +            /* +             * attempt to read in field, allowing each to be OPTIONAL +             */ + +            ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx, +                                       depth); +            if (!ret) { +                errtt = seqtt; +                goto err; +            } else if (ret == -1) { +                /* +                 * OPTIONAL component absent. Free and zero the field. +                 */ +                asn1_template_free(pseqval, seqtt); +                continue; +            } +            /* Update length */ +            len -= p - q; +        } + +        /* Check for EOC if expecting one */ +        if (seq_eoc && !asn1_check_eoc(&p, len)) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_MISSING_EOC); +            goto err; +        } +        /* Check all data read */ +        if (!seq_nolen && len) { +            ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_SEQUENCE_LENGTH_MISMATCH); +            goto err; +        } + +        /* +         * If we get here we've got no more data in the SEQUENCE, however we +         * may not have read all fields so check all remaining are OPTIONAL +         * and clear any that are. +         */ +        for (; i < it->tcount; tt++, i++) { +            const ASN1_TEMPLATE *seqtt; +            seqtt = asn1_do_adb(pval, tt, 1); +            if (seqtt == NULL) +                goto err; +            if (seqtt->flags & ASN1_TFLG_OPTIONAL) { +                ASN1_VALUE **pseqval; +                pseqval = asn1_get_field_ptr(pval, seqtt); +                asn1_template_free(pseqval, seqtt); +            } else { +                errtt = seqtt; +                ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_FIELD_MISSING); +                goto err; +            } +        } +        /* Save encoding */ +        if (!asn1_enc_save(pval, *in, p - *in, it)) +            goto auxerr; +        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL)) +            goto auxerr; +        *in = p; +        return 1; + +    default: +        return 0; +    } + auxerr: +    ASN1err(ASN1_F_ASN1_ITEM_EMBED_D2I, ASN1_R_AUX_ERROR); + err: +    if (errtt) +        ERR_add_error_data(4, "Field=", errtt->field_name, +                           ", Type=", it->sname); +    else +        ERR_add_error_data(2, "Type=", it->sname); +    return 0; +} + +/* + * Templates are handled with two separate functions. One handles any + * EXPLICIT tag and the other handles the rest. + */ + +static int asn1_template_ex_d2i(ASN1_VALUE **val, +                                const unsigned char **in, long inlen, +                                const ASN1_TEMPLATE *tt, char opt, +                                ASN1_TLC *ctx, int depth) +{ +    int flags, aclass; +    int ret; +    long len; +    const unsigned char *p, *q; +    char exp_eoc; +    if (!val) +        return 0; +    flags = tt->flags; +    aclass = flags & ASN1_TFLG_TAG_CLASS; + +    p = *in; + +    /* Check if EXPLICIT tag expected */ +    if (flags & ASN1_TFLG_EXPTAG) { +        char cst; +        /* +         * Need to work out amount of data available to the inner content and +         * where it starts: so read in EXPLICIT header to get the info. +         */ +        ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst, +                              &p, inlen, tt->tag, aclass, opt, ctx); +        q = p; +        if (!ret) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } else if (ret == -1) +            return -1; +        if (!cst) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, +                    ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED); +            return 0; +        } +        /* We've found the field so it can't be OPTIONAL now */ +        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx, depth); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } +        /* We read the field in OK so update length */ +        len -= p - q; +        if (exp_eoc) { +            /* If NDEF we must have an EOC here */ +            if (!asn1_check_eoc(&p, len)) { +                ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, ASN1_R_MISSING_EOC); +                goto err; +            } +        } else { +            /* +             * Otherwise we must hit the EXPLICIT tag end or its an error +             */ +            if (len) { +                ASN1err(ASN1_F_ASN1_TEMPLATE_EX_D2I, +                        ASN1_R_EXPLICIT_LENGTH_MISMATCH); +                goto err; +            } +        } +    } else +        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx, depth); + +    *in = p; +    return 1; + + err: +    return 0; +} + +static int asn1_template_noexp_d2i(ASN1_VALUE **val, +                                   const unsigned char **in, long len, +                                   const ASN1_TEMPLATE *tt, char opt, +                                   ASN1_TLC *ctx, int depth) +{ +    int flags, aclass; +    int ret; +    ASN1_VALUE *tval; +    const unsigned char *p, *q; +    if (!val) +        return 0; +    flags = tt->flags; +    aclass = flags & ASN1_TFLG_TAG_CLASS; + +    p = *in; +    q = p; + +    /* +     * If field is embedded then val needs fixing so it is a pointer to +     * a pointer to a field. +     */ +    if (tt->flags & ASN1_TFLG_EMBED) { +        tval = (ASN1_VALUE *)val; +        val = &tval; +    } + +    if (flags & ASN1_TFLG_SK_MASK) { +        /* SET OF, SEQUENCE OF */ +        int sktag, skaclass; +        char sk_eoc; +        /* First work out expected inner tag value */ +        if (flags & ASN1_TFLG_IMPTAG) { +            sktag = tt->tag; +            skaclass = aclass; +        } else { +            skaclass = V_ASN1_UNIVERSAL; +            if (flags & ASN1_TFLG_SET_OF) +                sktag = V_ASN1_SET; +            else +                sktag = V_ASN1_SEQUENCE; +        } +        /* Get the tag */ +        ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL, +                              &p, len, sktag, skaclass, opt, ctx); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } else if (ret == -1) +            return -1; +        if (!*val) +            *val = (ASN1_VALUE *)OPENSSL_sk_new_null(); +        else { +            /* +             * We've got a valid STACK: free up any items present +             */ +            STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val; +            ASN1_VALUE *vtmp; +            while (sk_ASN1_VALUE_num(sktmp) > 0) { +                vtmp = sk_ASN1_VALUE_pop(sktmp); +                ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item)); +            } +        } + +        if (!*val) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); +            goto err; +        } + +        /* Read as many items as we can */ +        while (len > 0) { +            ASN1_VALUE *skfield; +            q = p; +            /* See if EOC found */ +            if (asn1_check_eoc(&p, len)) { +                if (!sk_eoc) { +                    ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, +                            ASN1_R_UNEXPECTED_EOC); +                    goto err; +                } +                len -= p - q; +                sk_eoc = 0; +                break; +            } +            skfield = NULL; +            if (!asn1_item_embed_d2i(&skfield, &p, len, +                                     ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx, +                                     depth)) { +                ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, +                        ERR_R_NESTED_ASN1_ERROR); +                /* |skfield| may be partially allocated despite failure. */ +                ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); +                goto err; +            } +            len -= p - q; +            if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) { +                ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_MALLOC_FAILURE); +                ASN1_item_free(skfield, ASN1_ITEM_ptr(tt->item)); +                goto err; +            } +        } +        if (sk_eoc) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ASN1_R_MISSING_EOC); +            goto err; +        } +    } else if (flags & ASN1_TFLG_IMPTAG) { +        /* IMPLICIT tagging */ +        ret = asn1_item_embed_d2i(val, &p, len, +                                  ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, +                                  ctx, depth); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } else if (ret == -1) +            return -1; +    } else { +        /* Nothing special */ +        ret = asn1_item_embed_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item), +                                  -1, 0, opt, ctx, depth); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NOEXP_D2I, ERR_R_NESTED_ASN1_ERROR); +            goto err; +        } else if (ret == -1) +            return -1; +    } + +    *in = p; +    return 1; + + err: +    return 0; +} + +static int asn1_d2i_ex_primitive(ASN1_VALUE **pval, +                                 const unsigned char **in, long inlen, +                                 const ASN1_ITEM *it, +                                 int tag, int aclass, char opt, ASN1_TLC *ctx) +{ +    int ret = 0, utype; +    long plen; +    char cst, inf, free_cont = 0; +    const unsigned char *p; +    BUF_MEM buf = { 0, NULL, 0, 0 }; +    const unsigned char *cont = NULL; +    long len; +    if (!pval) { +        ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_NULL); +        return 0;               /* Should never happen */ +    } + +    if (it->itype == ASN1_ITYPE_MSTRING) { +        utype = tag; +        tag = -1; +    } else +        utype = it->utype; + +    if (utype == V_ASN1_ANY) { +        /* If type is ANY need to figure out type from tag */ +        unsigned char oclass; +        if (tag >= 0) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_ILLEGAL_TAGGED_ANY); +            return 0; +        } +        if (opt) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, +                    ASN1_R_ILLEGAL_OPTIONAL_ANY); +            return 0; +        } +        p = *in; +        ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL, +                              &p, inlen, -1, 0, 0, ctx); +        if (!ret) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } +        if (oclass != V_ASN1_UNIVERSAL) +            utype = V_ASN1_OTHER; +    } +    if (tag == -1) { +        tag = utype; +        aclass = V_ASN1_UNIVERSAL; +    } +    p = *in; +    /* Check header */ +    ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst, +                          &p, inlen, tag, aclass, opt, ctx); +    if (!ret) { +        ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_NESTED_ASN1_ERROR); +        return 0; +    } else if (ret == -1) +        return -1; +    ret = 0; +    /* SEQUENCE, SET and "OTHER" are left in encoded form */ +    if ((utype == V_ASN1_SEQUENCE) +        || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) { +        /* +         * Clear context cache for type OTHER because the auto clear when we +         * have a exact match won't work +         */ +        if (utype == V_ASN1_OTHER) { +            asn1_tlc_clear(ctx); +        } +        /* SEQUENCE and SET must be constructed */ +        else if (!cst) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, +                    ASN1_R_TYPE_NOT_CONSTRUCTED); +            return 0; +        } + +        cont = *in; +        /* If indefinite length constructed find the real end */ +        if (inf) { +            if (!asn1_find_end(&p, plen, inf)) +                goto err; +            len = p - cont; +        } else { +            len = p - cont + plen; +            p += plen; +        } +    } else if (cst) { +        if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN +            || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER +            || utype == V_ASN1_ENUMERATED) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ASN1_R_TYPE_NOT_PRIMITIVE); +            return 0; +        } + +        /* Free any returned 'buf' content */ +        free_cont = 1; +        /* +         * Should really check the internal tags are correct but some things +         * may get this wrong. The relevant specs say that constructed string +         * types should be OCTET STRINGs internally irrespective of the type. +         * So instead just check for UNIVERSAL class and ignore the tag. +         */ +        if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) { +            goto err; +        } +        len = buf.length; +        /* Append a final null to string */ +        if (!BUF_MEM_grow_clean(&buf, len + 1)) { +            ASN1err(ASN1_F_ASN1_D2I_EX_PRIMITIVE, ERR_R_MALLOC_FAILURE); +            goto err; +        } +        buf.data[len] = 0; +        cont = (const unsigned char *)buf.data; +    } else { +        cont = p; +        len = plen; +        p += plen; +    } + +    /* We now have content length and type: translate into a structure */ +    /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */ +    if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it)) +        goto err; + +    *in = p; +    ret = 1; + err: +    if (free_cont) +        OPENSSL_free(buf.data); +    return ret; +} + +/* Translate ASN1 content octets into a structure */ + +static int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                       int utype, char *free_cont, const ASN1_ITEM *it) +{ +    ASN1_VALUE **opval = NULL; +    ASN1_STRING *stmp; +    ASN1_TYPE *typ = NULL; +    int ret = 0; +    const ASN1_PRIMITIVE_FUNCS *pf; +    ASN1_INTEGER **tint; +    pf = it->funcs; + +    if (pf && pf->prim_c2i) +        return pf->prim_c2i(pval, cont, len, utype, free_cont, it); +    /* If ANY type clear type and set pointer to internal value */ +    if (it->utype == V_ASN1_ANY) { +        if (!*pval) { +            typ = ASN1_TYPE_new(); +            if (typ == NULL) +                goto err; +            *pval = (ASN1_VALUE *)typ; +        } else +            typ = (ASN1_TYPE *)*pval; + +        if (utype != typ->type) +            ASN1_TYPE_set(typ, utype, NULL); +        opval = pval; +        pval = &typ->value.asn1_value; +    } +    switch (utype) { +    case V_ASN1_OBJECT: +        if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len)) +            goto err; +        break; + +    case V_ASN1_NULL: +        if (len) { +            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_NULL_IS_WRONG_LENGTH); +            goto err; +        } +        *pval = (ASN1_VALUE *)1; +        break; + +    case V_ASN1_BOOLEAN: +        if (len != 1) { +            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BOOLEAN_IS_WRONG_LENGTH); +            goto err; +        } else { +            ASN1_BOOLEAN *tbool; +            tbool = (ASN1_BOOLEAN *)pval; +            *tbool = *cont; +        } +        break; + +    case V_ASN1_BIT_STRING: +        if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len)) +            goto err; +        break; + +    case V_ASN1_INTEGER: +    case V_ASN1_ENUMERATED: +        tint = (ASN1_INTEGER **)pval; +        if (!c2i_ASN1_INTEGER(tint, &cont, len)) +            goto err; +        /* Fixup type to match the expected form */ +        (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG); +        break; + +    case V_ASN1_OCTET_STRING: +    case V_ASN1_NUMERICSTRING: +    case V_ASN1_PRINTABLESTRING: +    case V_ASN1_T61STRING: +    case V_ASN1_VIDEOTEXSTRING: +    case V_ASN1_IA5STRING: +    case V_ASN1_UTCTIME: +    case V_ASN1_GENERALIZEDTIME: +    case V_ASN1_GRAPHICSTRING: +    case V_ASN1_VISIBLESTRING: +    case V_ASN1_GENERALSTRING: +    case V_ASN1_UNIVERSALSTRING: +    case V_ASN1_BMPSTRING: +    case V_ASN1_UTF8STRING: +    case V_ASN1_OTHER: +    case V_ASN1_SET: +    case V_ASN1_SEQUENCE: +    default: +        if (utype == V_ASN1_BMPSTRING && (len & 1)) { +            ASN1err(ASN1_F_ASN1_EX_C2I, ASN1_R_BMPSTRING_IS_WRONG_LENGTH); +            goto err; +        } +        if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) { +            ASN1err(ASN1_F_ASN1_EX_C2I, +                    ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH); +            goto err; +        } +        /* All based on ASN1_STRING and handled the same */ +        if (!*pval) { +            stmp = ASN1_STRING_type_new(utype); +            if (stmp == NULL) { +                ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); +                goto err; +            } +            *pval = (ASN1_VALUE *)stmp; +        } else { +            stmp = (ASN1_STRING *)*pval; +            stmp->type = utype; +        } +        /* If we've already allocated a buffer use it */ +        if (*free_cont) { +            OPENSSL_free(stmp->data); +            stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */ +            stmp->length = len; +            *free_cont = 0; +        } else { +            if (!ASN1_STRING_set(stmp, cont, len)) { +                ASN1err(ASN1_F_ASN1_EX_C2I, ERR_R_MALLOC_FAILURE); +                ASN1_STRING_free(stmp); +                *pval = NULL; +                goto err; +            } +        } +        break; +    } +    /* If ASN1_ANY and NULL type fix up value */ +    if (typ && (utype == V_ASN1_NULL)) +        typ->value.ptr = NULL; + +    ret = 1; + err: +    if (!ret) { +        ASN1_TYPE_free(typ); +        if (opval) +            *opval = NULL; +    } +    return ret; +} + +/* + * This function finds the end of an ASN1 structure when passed its maximum + * length, whether it is indefinite length and a pointer to the content. This + * is more efficient than calling asn1_collect because it does not recurse on + * each indefinite length header. + */ + +static int asn1_find_end(const unsigned char **in, long len, char inf) +{ +    uint32_t expected_eoc; +    long plen; +    const unsigned char *p = *in, *q; +    /* If not indefinite length constructed just add length */ +    if (inf == 0) { +        *in += len; +        return 1; +    } +    expected_eoc = 1; +    /* +     * Indefinite length constructed form. Find the end when enough EOCs are +     * found. If more indefinite length constructed headers are encountered +     * increment the expected eoc count otherwise just skip to the end of the +     * data. +     */ +    while (len > 0) { +        if (asn1_check_eoc(&p, len)) { +            expected_eoc--; +            if (expected_eoc == 0) +                break; +            len -= 2; +            continue; +        } +        q = p; +        /* Just read in a header: only care about the length */ +        if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len, +                             -1, 0, 0, NULL)) { +            ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } +        if (inf) { +            if (expected_eoc == UINT32_MAX) { +                ASN1err(ASN1_F_ASN1_FIND_END, ERR_R_NESTED_ASN1_ERROR); +                return 0; +            } +            expected_eoc++; +        } else { +            p += plen; +        } +        len -= p - q; +    } +    if (expected_eoc) { +        ASN1err(ASN1_F_ASN1_FIND_END, ASN1_R_MISSING_EOC); +        return 0; +    } +    *in = p; +    return 1; +} + +/* + * This function collects the asn1 data from a constructed string type into + * a buffer. The values of 'in' and 'len' should refer to the contents of the + * constructed type and 'inf' should be set if it is indefinite length. + */ + +#ifndef ASN1_MAX_STRING_NEST +/* + * This determines how many levels of recursion are permitted in ASN1 string + * types. If it is not limited stack overflows can occur. If set to zero no + * recursion is allowed at all. Although zero should be adequate examples + * exist that require a value of 1. So 5 should be more than enough. + */ +# define ASN1_MAX_STRING_NEST 5 +#endif + +static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len, +                        char inf, int tag, int aclass, int depth) +{ +    const unsigned char *p, *q; +    long plen; +    char cst, ininf; +    p = *in; +    inf &= 1; +    /* +     * If no buffer and not indefinite length constructed just pass over the +     * encoded data +     */ +    if (!buf && !inf) { +        *in += len; +        return 1; +    } +    while (len > 0) { +        q = p; +        /* Check for EOC */ +        if (asn1_check_eoc(&p, len)) { +            /* +             * EOC is illegal outside indefinite length constructed form +             */ +            if (!inf) { +                ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_UNEXPECTED_EOC); +                return 0; +            } +            inf = 0; +            break; +        } + +        if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p, +                             len, tag, aclass, 0, NULL)) { +            ASN1err(ASN1_F_ASN1_COLLECT, ERR_R_NESTED_ASN1_ERROR); +            return 0; +        } + +        /* If indefinite length constructed update max length */ +        if (cst) { +            if (depth >= ASN1_MAX_STRING_NEST) { +                ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_NESTED_ASN1_STRING); +                return 0; +            } +            if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1)) +                return 0; +        } else if (plen && !collect_data(buf, &p, plen)) +            return 0; +        len -= p - q; +    } +    if (inf) { +        ASN1err(ASN1_F_ASN1_COLLECT, ASN1_R_MISSING_EOC); +        return 0; +    } +    *in = p; +    return 1; +} + +static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen) +{ +    int len; +    if (buf) { +        len = buf->length; +        if (!BUF_MEM_grow_clean(buf, len + plen)) { +            ASN1err(ASN1_F_COLLECT_DATA, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        memcpy(buf->data + len, *p, plen); +    } +    *p += plen; +    return 1; +} + +/* Check for ASN1 EOC and swallow it if found */ + +static int asn1_check_eoc(const unsigned char **in, long len) +{ +    const unsigned char *p; +    if (len < 2) +        return 0; +    p = *in; +    if (!p[0] && !p[1]) { +        *in += 2; +        return 1; +    } +    return 0; +} + +/* + * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the + * length for indefinite length constructed form, we don't know the exact + * length but we can set an upper bound to the amount of data available minus + * the header length just read. + */ + +static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass, +                           char *inf, char *cst, +                           const unsigned char **in, long len, +                           int exptag, int expclass, char opt, ASN1_TLC *ctx) +{ +    int i; +    int ptag, pclass; +    long plen; +    const unsigned char *p, *q; +    p = *in; +    q = p; + +    if (ctx && ctx->valid) { +        i = ctx->ret; +        plen = ctx->plen; +        pclass = ctx->pclass; +        ptag = ctx->ptag; +        p += ctx->hdrlen; +    } else { +        i = ASN1_get_object(&p, &plen, &ptag, &pclass, len); +        if (ctx) { +            ctx->ret = i; +            ctx->plen = plen; +            ctx->pclass = pclass; +            ctx->ptag = ptag; +            ctx->hdrlen = p - q; +            ctx->valid = 1; +            /* +             * If definite length, and no error, length + header can't exceed +             * total amount of data available. +             */ +            if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) { +                ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_TOO_LONG); +                asn1_tlc_clear(ctx); +                return 0; +            } +        } +    } + +    if (i & 0x80) { +        ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_BAD_OBJECT_HEADER); +        asn1_tlc_clear(ctx); +        return 0; +    } +    if (exptag >= 0) { +        if ((exptag != ptag) || (expclass != pclass)) { +            /* +             * If type is OPTIONAL, not an error: indicate missing type. +             */ +            if (opt) +                return -1; +            asn1_tlc_clear(ctx); +            ASN1err(ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG); +            return 0; +        } +        /* +         * We have a tag and class match: assume we are going to do something +         * with it +         */ +        asn1_tlc_clear(ctx); +    } + +    if (i & 1) +        plen = len - (p - q); + +    if (inf) +        *inf = i & 1; + +    if (cst) +        *cst = i & V_ASN1_CONSTRUCTED; + +    if (olen) +        *olen = plen; + +    if (oclass) +        *oclass = pclass; + +    if (otag) +        *otag = ptag; + +    *in = p; +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_enc.c b/openssl-1.1.0h/crypto/asn1/tasn_enc.c new file mode 100644 index 0000000..caa4869 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_enc.c @@ -0,0 +1,605 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <string.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, +                                 const ASN1_ITEM *it, int tag, int aclass); +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, +                            int skcontlen, const ASN1_ITEM *item, +                            int do_sort, int iclass); +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +                                const ASN1_TEMPLATE *tt, int tag, int aclass); +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, +                               const ASN1_ITEM *it, int flags); +static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, +                       const ASN1_ITEM *it); + +/* + * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use + * indefinite length constructed encoding, where appropriate + */ + +int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, +                       const ASN1_ITEM *it) +{ +    return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF); +} + +int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it) +{ +    return asn1_item_flags_i2d(val, out, it, 0); +} + +/* + * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out' + * points to a buffer to output the data to. The new i2d has one additional + * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is + * allocated and populated with the encoding. + */ + +static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out, +                               const ASN1_ITEM *it, int flags) +{ +    if (out && !*out) { +        unsigned char *p, *buf; +        int len; +        len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags); +        if (len <= 0) +            return len; +        buf = OPENSSL_malloc(len); +        if (buf == NULL) +            return -1; +        p = buf; +        ASN1_item_ex_i2d(&val, &p, it, -1, flags); +        *out = buf; +        return len; +    } + +    return ASN1_item_ex_i2d(&val, out, it, -1, flags); +} + +/* + * Encode an item, taking care of IMPLICIT tagging (if any). This function + * performs the normal item handling: it can be used in external types. + */ + +int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +                     const ASN1_ITEM *it, int tag, int aclass) +{ +    const ASN1_TEMPLATE *tt = NULL; +    int i, seqcontlen, seqlen, ndef = 1; +    const ASN1_EXTERN_FUNCS *ef; +    const ASN1_AUX *aux = it->funcs; +    ASN1_aux_cb *asn1_cb = 0; + +    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) +        return 0; + +    if (aux && aux->asn1_cb) +        asn1_cb = aux->asn1_cb; + +    switch (it->itype) { + +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) +            return asn1_template_ex_i2d(pval, out, it->templates, +                                        tag, aclass); +        return asn1_i2d_ex_primitive(pval, out, it, tag, aclass); + +    case ASN1_ITYPE_MSTRING: +        return asn1_i2d_ex_primitive(pval, out, it, -1, aclass); + +    case ASN1_ITYPE_CHOICE: +        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) +            return 0; +        i = asn1_get_choice_selector(pval, it); +        if ((i >= 0) && (i < it->tcount)) { +            ASN1_VALUE **pchval; +            const ASN1_TEMPLATE *chtt; +            chtt = it->templates + i; +            pchval = asn1_get_field_ptr(pval, chtt); +            return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass); +        } +        /* Fixme: error condition if selector out of range */ +        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) +            return 0; +        break; + +    case ASN1_ITYPE_EXTERN: +        /* If new style i2d it does all the work */ +        ef = it->funcs; +        return ef->asn1_ex_i2d(pval, out, it, tag, aclass); + +    case ASN1_ITYPE_NDEF_SEQUENCE: +        /* Use indefinite length constructed if requested */ +        if (aclass & ASN1_TFLG_NDEF) +            ndef = 2; +        /* fall through */ + +    case ASN1_ITYPE_SEQUENCE: +        i = asn1_enc_restore(&seqcontlen, out, pval, it); +        /* An error occurred */ +        if (i < 0) +            return 0; +        /* We have a valid cached encoding... */ +        if (i > 0) +            return seqcontlen; +        /* Otherwise carry on */ +        seqcontlen = 0; +        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */ +        if (tag == -1) { +            tag = V_ASN1_SEQUENCE; +            /* Retain any other flags in aclass */ +            aclass = (aclass & ~ASN1_TFLG_TAG_CLASS) +                | V_ASN1_UNIVERSAL; +        } +        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL)) +            return 0; +        /* First work out sequence content length */ +        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { +            const ASN1_TEMPLATE *seqtt; +            ASN1_VALUE **pseqval; +            int tmplen; +            seqtt = asn1_do_adb(pval, tt, 1); +            if (!seqtt) +                return 0; +            pseqval = asn1_get_field_ptr(pval, seqtt); +            tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass); +            if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen)) +                return -1; +            seqcontlen += tmplen; +        } + +        seqlen = ASN1_object_size(ndef, seqcontlen, tag); +        if (!out || seqlen == -1) +            return seqlen; +        /* Output SEQUENCE header */ +        ASN1_put_object(out, ndef, seqcontlen, tag, aclass); +        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { +            const ASN1_TEMPLATE *seqtt; +            ASN1_VALUE **pseqval; +            seqtt = asn1_do_adb(pval, tt, 1); +            if (!seqtt) +                return 0; +            pseqval = asn1_get_field_ptr(pval, seqtt); +            /* FIXME: check for errors in enhanced version */ +            asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass); +        } +        if (ndef == 2) +            ASN1_put_eoc(out); +        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL)) +            return 0; +        return seqlen; + +    default: +        return 0; + +    } +    return 0; +} + +static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out, +                                const ASN1_TEMPLATE *tt, int tag, int iclass) +{ +    int i, ret, flags, ttag, tclass, ndef; +    ASN1_VALUE *tval; +    flags = tt->flags; + +    /* +     * If field is embedded then val needs fixing so it is a pointer to +     * a pointer to a field. +     */ +    if (flags & ASN1_TFLG_EMBED) { +        tval = (ASN1_VALUE *)pval; +        pval = &tval; +    } +    /* +     * Work out tag and class to use: tagging may come either from the +     * template or the arguments, not both because this would create +     * ambiguity. Additionally the iclass argument may contain some +     * additional flags which should be noted and passed down to other +     * levels. +     */ +    if (flags & ASN1_TFLG_TAG_MASK) { +        /* Error if argument and template tagging */ +        if (tag != -1) +            /* FIXME: error code here */ +            return -1; +        /* Get tagging from template */ +        ttag = tt->tag; +        tclass = flags & ASN1_TFLG_TAG_CLASS; +    } else if (tag != -1) { +        /* No template tagging, get from arguments */ +        ttag = tag; +        tclass = iclass & ASN1_TFLG_TAG_CLASS; +    } else { +        ttag = -1; +        tclass = 0; +    } +    /* +     * Remove any class mask from iflag. +     */ +    iclass &= ~ASN1_TFLG_TAG_CLASS; + +    /* +     * At this point 'ttag' contains the outer tag to use, 'tclass' is the +     * class and iclass is any flags passed to this function. +     */ + +    /* if template and arguments require ndef, use it */ +    if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF)) +        ndef = 2; +    else +        ndef = 1; + +    if (flags & ASN1_TFLG_SK_MASK) { +        /* SET OF, SEQUENCE OF */ +        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; +        int isset, sktag, skaclass; +        int skcontlen, sklen; +        ASN1_VALUE *skitem; + +        if (!*pval) +            return 0; + +        if (flags & ASN1_TFLG_SET_OF) { +            isset = 1; +            /* 2 means we reorder */ +            if (flags & ASN1_TFLG_SEQUENCE_OF) +                isset = 2; +        } else +            isset = 0; + +        /* +         * Work out inner tag value: if EXPLICIT or no tagging use underlying +         * type. +         */ +        if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) { +            sktag = ttag; +            skaclass = tclass; +        } else { +            skaclass = V_ASN1_UNIVERSAL; +            if (isset) +                sktag = V_ASN1_SET; +            else +                sktag = V_ASN1_SEQUENCE; +        } + +        /* Determine total length of items */ +        skcontlen = 0; +        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { +            int tmplen; +            skitem = sk_ASN1_VALUE_value(sk, i); +            tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item), +                                      -1, iclass); +            if (tmplen == -1 || (skcontlen > INT_MAX - tmplen)) +                return -1; +            skcontlen += tmplen; +        } +        sklen = ASN1_object_size(ndef, skcontlen, sktag); +        if (sklen == -1) +            return -1; +        /* If EXPLICIT need length of surrounding tag */ +        if (flags & ASN1_TFLG_EXPTAG) +            ret = ASN1_object_size(ndef, sklen, ttag); +        else +            ret = sklen; + +        if (!out || ret == -1) +            return ret; + +        /* Now encode this lot... */ +        /* EXPLICIT tag */ +        if (flags & ASN1_TFLG_EXPTAG) +            ASN1_put_object(out, ndef, sklen, ttag, tclass); +        /* SET or SEQUENCE and IMPLICIT tag */ +        ASN1_put_object(out, ndef, skcontlen, sktag, skaclass); +        /* And the stuff itself */ +        asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item), +                         isset, iclass); +        if (ndef == 2) { +            ASN1_put_eoc(out); +            if (flags & ASN1_TFLG_EXPTAG) +                ASN1_put_eoc(out); +        } + +        return ret; +    } + +    if (flags & ASN1_TFLG_EXPTAG) { +        /* EXPLICIT tagging */ +        /* Find length of tagged item */ +        i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass); +        if (!i) +            return 0; +        /* Find length of EXPLICIT tag */ +        ret = ASN1_object_size(ndef, i, ttag); +        if (out && ret != -1) { +            /* Output tag and item */ +            ASN1_put_object(out, ndef, i, ttag, tclass); +            ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass); +            if (ndef == 2) +                ASN1_put_eoc(out); +        } +        return ret; +    } + +    /* Either normal or IMPLICIT tagging: combine class and flags */ +    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), +                            ttag, tclass | iclass); + +} + +/* Temporary structure used to hold DER encoding of items for SET OF */ + +typedef struct { +    unsigned char *data; +    int length; +    ASN1_VALUE *field; +} DER_ENC; + +static int der_cmp(const void *a, const void *b) +{ +    const DER_ENC *d1 = a, *d2 = b; +    int cmplen, i; +    cmplen = (d1->length < d2->length) ? d1->length : d2->length; +    i = memcmp(d1->data, d2->data, cmplen); +    if (i) +        return i; +    return d1->length - d2->length; +} + +/* Output the content octets of SET OF or SEQUENCE OF */ + +static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out, +                            int skcontlen, const ASN1_ITEM *item, +                            int do_sort, int iclass) +{ +    int i; +    ASN1_VALUE *skitem; +    unsigned char *tmpdat = NULL, *p = NULL; +    DER_ENC *derlst = NULL, *tder; +    if (do_sort) { +        /* Don't need to sort less than 2 items */ +        if (sk_ASN1_VALUE_num(sk) < 2) +            do_sort = 0; +        else { +            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk) +                                    * sizeof(*derlst)); +            if (derlst == NULL) +                return 0; +            tmpdat = OPENSSL_malloc(skcontlen); +            if (tmpdat == NULL) { +                OPENSSL_free(derlst); +                return 0; +            } +        } +    } +    /* If not sorting just output each item */ +    if (!do_sort) { +        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { +            skitem = sk_ASN1_VALUE_value(sk, i); +            ASN1_item_ex_i2d(&skitem, out, item, -1, iclass); +        } +        return 1; +    } +    p = tmpdat; + +    /* Doing sort: build up a list of each member's DER encoding */ +    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { +        skitem = sk_ASN1_VALUE_value(sk, i); +        tder->data = p; +        tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass); +        tder->field = skitem; +    } + +    /* Now sort them */ +    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp); +    /* Output sorted DER encoding */ +    p = *out; +    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) { +        memcpy(p, tder->data, tder->length); +        p += tder->length; +    } +    *out = p; +    /* If do_sort is 2 then reorder the STACK */ +    if (do_sort == 2) { +        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) +            (void)sk_ASN1_VALUE_set(sk, i, tder->field); +    } +    OPENSSL_free(derlst); +    OPENSSL_free(tmpdat); +    return 1; +} + +static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out, +                                 const ASN1_ITEM *it, int tag, int aclass) +{ +    int len; +    int utype; +    int usetag; +    int ndef = 0; + +    utype = it->utype; + +    /* +     * Get length of content octets and maybe find out the underlying type. +     */ + +    len = asn1_ex_i2c(pval, NULL, &utype, it); + +    /* +     * If SEQUENCE, SET or OTHER then header is included in pseudo content +     * octets so don't include tag+length. We need to check here because the +     * call to asn1_ex_i2c() could change utype. +     */ +    if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) || +        (utype == V_ASN1_OTHER)) +        usetag = 0; +    else +        usetag = 1; + +    /* -1 means omit type */ + +    if (len == -1) +        return 0; + +    /* -2 return is special meaning use ndef */ +    if (len == -2) { +        ndef = 2; +        len = 0; +    } + +    /* If not implicitly tagged get tag from underlying type */ +    if (tag == -1) +        tag = utype; + +    /* Output tag+length followed by content octets */ +    if (out) { +        if (usetag) +            ASN1_put_object(out, ndef, len, tag, aclass); +        asn1_ex_i2c(pval, *out, &utype, it); +        if (ndef) +            ASN1_put_eoc(out); +        else +            *out += len; +    } + +    if (usetag) +        return ASN1_object_size(ndef, len, tag); +    return len; +} + +/* Produce content octets from a structure */ + +static int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype, +                       const ASN1_ITEM *it) +{ +    ASN1_BOOLEAN *tbool = NULL; +    ASN1_STRING *strtmp; +    ASN1_OBJECT *otmp; +    int utype; +    const unsigned char *cont; +    unsigned char c; +    int len; +    const ASN1_PRIMITIVE_FUNCS *pf; +    pf = it->funcs; +    if (pf && pf->prim_i2c) +        return pf->prim_i2c(pval, cout, putype, it); + +    /* Should type be omitted? */ +    if ((it->itype != ASN1_ITYPE_PRIMITIVE) +        || (it->utype != V_ASN1_BOOLEAN)) { +        if (!*pval) +            return -1; +    } + +    if (it->itype == ASN1_ITYPE_MSTRING) { +        /* If MSTRING type set the underlying type */ +        strtmp = (ASN1_STRING *)*pval; +        utype = strtmp->type; +        *putype = utype; +    } else if (it->utype == V_ASN1_ANY) { +        /* If ANY set type and pointer to value */ +        ASN1_TYPE *typ; +        typ = (ASN1_TYPE *)*pval; +        utype = typ->type; +        *putype = utype; +        pval = &typ->value.asn1_value; +    } else +        utype = *putype; + +    switch (utype) { +    case V_ASN1_OBJECT: +        otmp = (ASN1_OBJECT *)*pval; +        cont = otmp->data; +        len = otmp->length; +        break; + +    case V_ASN1_NULL: +        cont = NULL; +        len = 0; +        break; + +    case V_ASN1_BOOLEAN: +        tbool = (ASN1_BOOLEAN *)pval; +        if (*tbool == -1) +            return -1; +        if (it->utype != V_ASN1_ANY) { +            /* +             * Default handling if value == size field then omit +             */ +            if (*tbool && (it->size > 0)) +                return -1; +            if (!*tbool && !it->size) +                return -1; +        } +        c = (unsigned char)*tbool; +        cont = &c; +        len = 1; +        break; + +    case V_ASN1_BIT_STRING: +        return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval, +                                   cout ? &cout : NULL); + +    case V_ASN1_INTEGER: +    case V_ASN1_ENUMERATED: +        /* +         * These are all have the same content format as ASN1_INTEGER +         */ +        return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL); + +    case V_ASN1_OCTET_STRING: +    case V_ASN1_NUMERICSTRING: +    case V_ASN1_PRINTABLESTRING: +    case V_ASN1_T61STRING: +    case V_ASN1_VIDEOTEXSTRING: +    case V_ASN1_IA5STRING: +    case V_ASN1_UTCTIME: +    case V_ASN1_GENERALIZEDTIME: +    case V_ASN1_GRAPHICSTRING: +    case V_ASN1_VISIBLESTRING: +    case V_ASN1_GENERALSTRING: +    case V_ASN1_UNIVERSALSTRING: +    case V_ASN1_BMPSTRING: +    case V_ASN1_UTF8STRING: +    case V_ASN1_SEQUENCE: +    case V_ASN1_SET: +    default: +        /* All based on ASN1_STRING and handled the same */ +        strtmp = (ASN1_STRING *)*pval; +        /* Special handling for NDEF */ +        if ((it->size == ASN1_TFLG_NDEF) +            && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) { +            if (cout) { +                strtmp->data = cout; +                strtmp->length = 0; +            } +            /* Special return code */ +            return -2; +        } +        cont = strtmp->data; +        len = strtmp->length; + +        break; + +    } +    if (cout && len) +        memcpy(cout, cont, len); +    return len; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_fre.c b/openssl-1.1.0h/crypto/asn1/tasn_fre.c new file mode 100644 index 0000000..bbce489 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_fre.c @@ -0,0 +1,208 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include "asn1_locl.h" + +/* Free up an ASN1 structure */ + +void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it) +{ +    asn1_item_embed_free(&val, it, 0); +} + +void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    asn1_item_embed_free(pval, it, 0); +} + +void asn1_item_embed_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ +    const ASN1_TEMPLATE *tt = NULL, *seqtt; +    const ASN1_EXTERN_FUNCS *ef; +    const ASN1_AUX *aux = it->funcs; +    ASN1_aux_cb *asn1_cb; +    int i; + +    if (!pval) +        return; +    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval) +        return; +    if (aux && aux->asn1_cb) +        asn1_cb = aux->asn1_cb; +    else +        asn1_cb = 0; + +    switch (it->itype) { + +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) +            asn1_template_free(pval, it->templates); +        else +            asn1_primitive_free(pval, it, embed); +        break; + +    case ASN1_ITYPE_MSTRING: +        asn1_primitive_free(pval, it, embed); +        break; + +    case ASN1_ITYPE_CHOICE: +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); +            if (i == 2) +                return; +        } +        i = asn1_get_choice_selector(pval, it); +        if ((i >= 0) && (i < it->tcount)) { +            ASN1_VALUE **pchval; + +            tt = it->templates + i; +            pchval = asn1_get_field_ptr(pval, tt); +            asn1_template_free(pchval, tt); +        } +        if (asn1_cb) +            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); +        if (embed == 0) { +            OPENSSL_free(*pval); +            *pval = NULL; +        } +        break; + +    case ASN1_ITYPE_EXTERN: +        ef = it->funcs; +        if (ef && ef->asn1_ex_free) +            ef->asn1_ex_free(pval, it); +        break; + +    case ASN1_ITYPE_NDEF_SEQUENCE: +    case ASN1_ITYPE_SEQUENCE: +        if (asn1_do_lock(pval, -1, it) != 0) /* if error or ref-counter > 0 */ +            return; +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL); +            if (i == 2) +                return; +        } +        asn1_enc_free(pval, it); +        /* +         * If we free up as normal we will invalidate any ANY DEFINED BY +         * field and we won't be able to determine the type of the field it +         * defines. So free up in reverse order. +         */ +        tt = it->templates + it->tcount; +        for (i = 0; i < it->tcount; i++) { +            ASN1_VALUE **pseqval; + +            tt--; +            seqtt = asn1_do_adb(pval, tt, 0); +            if (!seqtt) +                continue; +            pseqval = asn1_get_field_ptr(pval, seqtt); +            asn1_template_free(pseqval, seqtt); +        } +        if (asn1_cb) +            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL); +        if (embed == 0) { +            OPENSSL_free(*pval); +            *pval = NULL; +        } +        break; +    } +} + +void asn1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ +    int embed = tt->flags & ASN1_TFLG_EMBED; +    ASN1_VALUE *tval; +    if (embed) { +        tval = (ASN1_VALUE *)pval; +        pval = &tval; +    } +    if (tt->flags & ASN1_TFLG_SK_MASK) { +        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval; +        int i; + +        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) { +            ASN1_VALUE *vtmp = sk_ASN1_VALUE_value(sk, i); + +            asn1_item_embed_free(&vtmp, ASN1_ITEM_ptr(tt->item), embed); +        } +        sk_ASN1_VALUE_free(sk); +        *pval = NULL; +    } else { +        asn1_item_embed_free(pval, ASN1_ITEM_ptr(tt->item), embed); +    } +} + +void asn1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ +    int utype; + +    /* Special case: if 'it' is a primitive with a free_func, use that. */ +    if (it) { +        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; + +        if (embed) { +            if (pf && pf->prim_clear) { +                pf->prim_clear(pval, it); +                return; +            } +        } else if (pf && pf->prim_free) { +            pf->prim_free(pval, it); +            return; +        } +    } + +    /* Special case: if 'it' is NULL, free contents of ASN1_TYPE */ +    if (!it) { +        ASN1_TYPE *typ = (ASN1_TYPE *)*pval; + +        utype = typ->type; +        pval = &typ->value.asn1_value; +        if (!*pval) +            return; +    } else if (it->itype == ASN1_ITYPE_MSTRING) { +        utype = -1; +        if (!*pval) +            return; +    } else { +        utype = it->utype; +        if ((utype != V_ASN1_BOOLEAN) && !*pval) +            return; +    } + +    switch (utype) { +    case V_ASN1_OBJECT: +        ASN1_OBJECT_free((ASN1_OBJECT *)*pval); +        break; + +    case V_ASN1_BOOLEAN: +        if (it) +            *(ASN1_BOOLEAN *)pval = it->size; +        else +            *(ASN1_BOOLEAN *)pval = -1; +        return; + +    case V_ASN1_NULL: +        break; + +    case V_ASN1_ANY: +        asn1_primitive_free(pval, NULL, 0); +        OPENSSL_free(*pval); +        break; + +    default: +        asn1_string_embed_free((ASN1_STRING *)*pval, embed); +        break; +    } +    *pval = NULL; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_new.c b/openssl-1.1.0h/crypto/asn1/tasn_new.c new file mode 100644 index 0000000..11c8040 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_new.c @@ -0,0 +1,348 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <openssl/asn1.h> +#include <openssl/objects.h> +#include <openssl/err.h> +#include <openssl/asn1t.h> +#include <string.h> +#include "asn1_locl.h" + +static int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, +                               int embed); +static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, +                              int embed); +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt); +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it); + +ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it) +{ +    ASN1_VALUE *ret = NULL; +    if (ASN1_item_ex_new(&ret, it) > 0) +        return ret; +    return NULL; +} + +/* Allocate an ASN1 structure */ + +int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    return asn1_item_embed_new(pval, it, 0); +} + +int asn1_item_embed_new(ASN1_VALUE **pval, const ASN1_ITEM *it, int embed) +{ +    const ASN1_TEMPLATE *tt = NULL; +    const ASN1_EXTERN_FUNCS *ef; +    const ASN1_AUX *aux = it->funcs; +    ASN1_aux_cb *asn1_cb; +    ASN1_VALUE **pseqval; +    int i; +    if (aux && aux->asn1_cb) +        asn1_cb = aux->asn1_cb; +    else +        asn1_cb = 0; + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_push(it->sname ? it->sname : "asn1_item_embed_new"); +#endif + +    switch (it->itype) { + +    case ASN1_ITYPE_EXTERN: +        ef = it->funcs; +        if (ef && ef->asn1_ex_new) { +            if (!ef->asn1_ex_new(pval, it)) +                goto memerr; +        } +        break; + +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) { +            if (!asn1_template_new(pval, it->templates)) +                goto memerr; +        } else if (!asn1_primitive_new(pval, it, embed)) +            goto memerr; +        break; + +    case ASN1_ITYPE_MSTRING: +        if (!asn1_primitive_new(pval, it, embed)) +            goto memerr; +        break; + +    case ASN1_ITYPE_CHOICE: +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); +            if (!i) +                goto auxerr; +            if (i == 2) { +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +                OPENSSL_mem_debug_pop(); +#endif +                return 1; +            } +        } +        if (embed) { +            memset(*pval, 0, it->size); +        } else { +            *pval = OPENSSL_zalloc(it->size); +            if (*pval == NULL) +                goto memerr; +        } +        asn1_set_choice_selector(pval, -1, it); +        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) +            goto auxerr2; +        break; + +    case ASN1_ITYPE_NDEF_SEQUENCE: +    case ASN1_ITYPE_SEQUENCE: +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL); +            if (!i) +                goto auxerr; +            if (i == 2) { +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +                OPENSSL_mem_debug_pop(); +#endif +                return 1; +            } +        } +        if (embed) { +            memset(*pval, 0, it->size); +        } else { +            *pval = OPENSSL_zalloc(it->size); +            if (*pval == NULL) +                goto memerr; +        } +        /* 0 : init. lock */ +        if (asn1_do_lock(pval, 0, it) < 0) { +            if (!embed) { +                OPENSSL_free(*pval); +                *pval = NULL; +            } +            goto memerr; +        } +        asn1_enc_init(pval, it); +        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) { +            pseqval = asn1_get_field_ptr(pval, tt); +            if (!asn1_template_new(pseqval, tt)) +                goto memerr2; +        } +        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL)) +            goto auxerr2; +        break; +    } +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_pop(); +#endif +    return 1; + + memerr2: +    asn1_item_embed_free(pval, it, embed); + memerr: +    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ERR_R_MALLOC_FAILURE); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_pop(); +#endif +    return 0; + + auxerr2: +    asn1_item_embed_free(pval, it, embed); + auxerr: +    ASN1err(ASN1_F_ASN1_ITEM_EMBED_NEW, ASN1_R_AUX_ERROR); +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_pop(); +#endif +    return 0; + +} + +static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    const ASN1_EXTERN_FUNCS *ef; + +    switch (it->itype) { + +    case ASN1_ITYPE_EXTERN: +        ef = it->funcs; +        if (ef && ef->asn1_ex_clear) +            ef->asn1_ex_clear(pval, it); +        else +            *pval = NULL; +        break; + +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) +            asn1_template_clear(pval, it->templates); +        else +            asn1_primitive_clear(pval, it); +        break; + +    case ASN1_ITYPE_MSTRING: +        asn1_primitive_clear(pval, it); +        break; + +    case ASN1_ITYPE_CHOICE: +    case ASN1_ITYPE_SEQUENCE: +    case ASN1_ITYPE_NDEF_SEQUENCE: +        *pval = NULL; +        break; +    } +} + +static int asn1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ +    const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item); +    int embed = tt->flags & ASN1_TFLG_EMBED; +    ASN1_VALUE *tval; +    int ret; +    if (embed) { +        tval = (ASN1_VALUE *)pval; +        pval = &tval; +    } +    if (tt->flags & ASN1_TFLG_OPTIONAL) { +        asn1_template_clear(pval, tt); +        return 1; +    } +    /* If ANY DEFINED BY nothing to do */ + +    if (tt->flags & ASN1_TFLG_ADB_MASK) { +        *pval = NULL; +        return 1; +    } +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_push(tt->field_name +            ? tt->field_name : "asn1_template_new"); +#endif +    /* If SET OF or SEQUENCE OF, its a STACK */ +    if (tt->flags & ASN1_TFLG_SK_MASK) { +        STACK_OF(ASN1_VALUE) *skval; +        skval = sk_ASN1_VALUE_new_null(); +        if (!skval) { +            ASN1err(ASN1_F_ASN1_TEMPLATE_NEW, ERR_R_MALLOC_FAILURE); +            ret = 0; +            goto done; +        } +        *pval = (ASN1_VALUE *)skval; +        ret = 1; +        goto done; +    } +    /* Otherwise pass it back to the item routine */ +    ret = asn1_item_embed_new(pval, it, embed); + done: +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +    OPENSSL_mem_debug_pop(); +#endif +    return ret; +} + +static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ +    /* If ADB or STACK just NULL the field */ +    if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK)) +        *pval = NULL; +    else +        asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item)); +} + +/* + * NB: could probably combine most of the real XXX_new() behaviour and junk + * all the old functions. + */ + +static int asn1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it, +                              int embed) +{ +    ASN1_TYPE *typ; +    ASN1_STRING *str; +    int utype; + +    if (!it) +        return 0; + +    if (it->funcs) { +        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; +        if (embed) { +            if (pf->prim_clear) { +                pf->prim_clear(pval, it); +                return 1; +            } +        } else if (pf->prim_new) { +            return pf->prim_new(pval, it); +        } +    } + +    if (it->itype == ASN1_ITYPE_MSTRING) +        utype = -1; +    else +        utype = it->utype; +    switch (utype) { +    case V_ASN1_OBJECT: +        *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef); +        return 1; + +    case V_ASN1_BOOLEAN: +        *(ASN1_BOOLEAN *)pval = it->size; +        return 1; + +    case V_ASN1_NULL: +        *pval = (ASN1_VALUE *)1; +        return 1; + +    case V_ASN1_ANY: +        typ = OPENSSL_malloc(sizeof(*typ)); +        if (typ == NULL) +            return 0; +        typ->value.ptr = NULL; +        typ->type = -1; +        *pval = (ASN1_VALUE *)typ; +        break; + +    default: +        if (embed) { +            str = *(ASN1_STRING **)pval; +            memset(str, 0, sizeof(*str)); +            str->type = utype; +            str->flags = ASN1_STRING_FLAG_EMBED; +        } else { +            str = ASN1_STRING_type_new(utype); +            *pval = (ASN1_VALUE *)str; +        } +        if (it->itype == ASN1_ITYPE_MSTRING && str) +            str->flags |= ASN1_STRING_FLAG_MSTRING; +        break; +    } +    if (*pval) +        return 1; +    return 0; +} + +static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    int utype; +    if (it && it->funcs) { +        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs; +        if (pf->prim_clear) +            pf->prim_clear(pval, it); +        else +            *pval = NULL; +        return; +    } +    if (!it || (it->itype == ASN1_ITYPE_MSTRING)) +        utype = -1; +    else +        utype = it->utype; +    if (utype == V_ASN1_BOOLEAN) +        *(ASN1_BOOLEAN *)pval = it->size; +    else +        *pval = NULL; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_prn.c b/openssl-1.1.0h/crypto/asn1/tasn_prn.c new file mode 100644 index 0000000..53a9ee8 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_prn.c @@ -0,0 +1,538 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#include "internal/asn1_int.h" +#include "asn1_locl.h" + +/* + * Print routines. + */ + +/* ASN1_PCTX routines */ + +static ASN1_PCTX default_pctx = { +    ASN1_PCTX_FLAGS_SHOW_ABSENT, /* flags */ +    0,                          /* nm_flags */ +    0,                          /* cert_flags */ +    0,                          /* oid_flags */ +    0                           /* str_flags */ +}; + +ASN1_PCTX *ASN1_PCTX_new(void) +{ +    ASN1_PCTX *ret; + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) { +        ASN1err(ASN1_F_ASN1_PCTX_NEW, ERR_R_MALLOC_FAILURE); +        return NULL; +    } +    return ret; +} + +void ASN1_PCTX_free(ASN1_PCTX *p) +{ +    OPENSSL_free(p); +} + +unsigned long ASN1_PCTX_get_flags(const ASN1_PCTX *p) +{ +    return p->flags; +} + +void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags) +{ +    p->flags = flags; +} + +unsigned long ASN1_PCTX_get_nm_flags(const ASN1_PCTX *p) +{ +    return p->nm_flags; +} + +void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags) +{ +    p->nm_flags = flags; +} + +unsigned long ASN1_PCTX_get_cert_flags(const ASN1_PCTX *p) +{ +    return p->cert_flags; +} + +void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags) +{ +    p->cert_flags = flags; +} + +unsigned long ASN1_PCTX_get_oid_flags(const ASN1_PCTX *p) +{ +    return p->oid_flags; +} + +void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags) +{ +    p->oid_flags = flags; +} + +unsigned long ASN1_PCTX_get_str_flags(const ASN1_PCTX *p) +{ +    return p->str_flags; +} + +void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags) +{ +    p->str_flags = flags; +} + +/* Main print routines */ + +static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +                               const ASN1_ITEM *it, +                               const char *fname, const char *sname, +                               int nohdr, const ASN1_PCTX *pctx); + +static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +                            const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx); + +static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, +                                const ASN1_ITEM *it, int indent, +                                const char *fname, const char *sname, +                                const ASN1_PCTX *pctx); + +static int asn1_print_fsname(BIO *out, int indent, +                             const char *fname, const char *sname, +                             const ASN1_PCTX *pctx); + +int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, +                    const ASN1_ITEM *it, const ASN1_PCTX *pctx) +{ +    const char *sname; +    if (pctx == NULL) +        pctx = &default_pctx; +    if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) +        sname = NULL; +    else +        sname = it->sname; +    return asn1_item_print_ctx(out, &ifld, indent, it, NULL, sname, 0, pctx); +} + +static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +                               const ASN1_ITEM *it, +                               const char *fname, const char *sname, +                               int nohdr, const ASN1_PCTX *pctx) +{ +    const ASN1_TEMPLATE *tt; +    const ASN1_EXTERN_FUNCS *ef; +    ASN1_VALUE **tmpfld; +    const ASN1_AUX *aux = it->funcs; +    ASN1_aux_cb *asn1_cb; +    ASN1_PRINT_ARG parg; +    int i; +    if (aux && aux->asn1_cb) { +        parg.out = out; +        parg.indent = indent; +        parg.pctx = pctx; +        asn1_cb = aux->asn1_cb; +    } else +        asn1_cb = 0; + +   if (((it->itype != ASN1_ITYPE_PRIMITIVE) +       || (it->utype != V_ASN1_BOOLEAN)) && *fld == NULL) { +        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT) { +            if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) +                return 0; +            if (BIO_puts(out, "<ABSENT>\n") <= 0) +                return 0; +        } +        return 1; +    } + +    switch (it->itype) { +    case ASN1_ITYPE_PRIMITIVE: +        if (it->templates) { +            if (!asn1_template_print_ctx(out, fld, indent, +                                         it->templates, pctx)) +                return 0; +            break; +        } +        /* fall through */ +    case ASN1_ITYPE_MSTRING: +        if (!asn1_primitive_print(out, fld, it, indent, fname, sname, pctx)) +            return 0; +        break; + +    case ASN1_ITYPE_EXTERN: +        if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) +            return 0; +        /* Use new style print routine if possible */ +        ef = it->funcs; +        if (ef && ef->asn1_ex_print) { +            i = ef->asn1_ex_print(out, fld, indent, "", pctx); +            if (!i) +                return 0; +            if ((i == 2) && (BIO_puts(out, "\n") <= 0)) +                return 0; +            return 1; +        } else if (sname && +                   BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0) +            return 0; +        break; + +    case ASN1_ITYPE_CHOICE: +        /* CHOICE type, get selector */ +        i = asn1_get_choice_selector(fld, it); +        /* This should never happen... */ +        if ((i < 0) || (i >= it->tcount)) { +            if (BIO_printf(out, "ERROR: selector [%d] invalid\n", i) <= 0) +                return 0; +            return 1; +        } +        tt = it->templates + i; +        tmpfld = asn1_get_field_ptr(fld, tt); +        if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx)) +            return 0; +        break; + +    case ASN1_ITYPE_SEQUENCE: +    case ASN1_ITYPE_NDEF_SEQUENCE: +        if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx)) +            return 0; +        if (fname || sname) { +            if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { +                if (BIO_puts(out, " {\n") <= 0) +                    return 0; +            } else { +                if (BIO_puts(out, "\n") <= 0) +                    return 0; +            } +        } + +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg); +            if (i == 0) +                return 0; +            if (i == 2) +                return 1; +        } + +        /* Print each field entry */ +        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) { +            const ASN1_TEMPLATE *seqtt; +            seqtt = asn1_do_adb(fld, tt, 1); +            if (!seqtt) +                return 0; +            tmpfld = asn1_get_field_ptr(fld, seqtt); +            if (!asn1_template_print_ctx(out, tmpfld, +                                         indent + 2, seqtt, pctx)) +                return 0; +        } +        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { +            if (BIO_printf(out, "%*s}\n", indent, "") < 0) +                return 0; +        } + +        if (asn1_cb) { +            i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg); +            if (i == 0) +                return 0; +        } +        break; + +    default: +        BIO_printf(out, "Unprocessed type %d\n", it->itype); +        return 0; +    } + +    return 1; +} + +static int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent, +                            const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx) +{ +    int i, flags; +    const char *sname, *fname; +    ASN1_VALUE *tfld; +    flags = tt->flags; +    if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME) +        sname = ASN1_ITEM_ptr(tt->item)->sname; +    else +        sname = NULL; +    if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) +        fname = NULL; +    else +        fname = tt->field_name; + +    /* +     * If field is embedded then fld needs fixing so it is a pointer to +     * a pointer to a field. +     */ +    if (flags & ASN1_TFLG_EMBED) { +        tfld = (ASN1_VALUE *)fld; +        fld = &tfld; +    } + +    if (flags & ASN1_TFLG_SK_MASK) { +        char *tname; +        ASN1_VALUE *skitem; +        STACK_OF(ASN1_VALUE) *stack; + +        /* SET OF, SEQUENCE OF */ +        if (fname) { +            if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF) { +                if (flags & ASN1_TFLG_SET_OF) +                    tname = "SET"; +                else +                    tname = "SEQUENCE"; +                if (BIO_printf(out, "%*s%s OF %s {\n", +                               indent, "", tname, tt->field_name) <= 0) +                    return 0; +            } else if (BIO_printf(out, "%*s%s:\n", indent, "", fname) <= 0) +                return 0; +        } +        stack = (STACK_OF(ASN1_VALUE) *)*fld; +        for (i = 0; i < sk_ASN1_VALUE_num(stack); i++) { +            if ((i > 0) && (BIO_puts(out, "\n") <= 0)) +                return 0; + +            skitem = sk_ASN1_VALUE_value(stack, i); +            if (!asn1_item_print_ctx(out, &skitem, indent + 2, +                                     ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, +                                     pctx)) +                return 0; +        } +        if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0) +            return 0; +        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE) { +            if (BIO_printf(out, "%*s}\n", indent, "") <= 0) +                return 0; +        } +        return 1; +    } +    return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item), +                               fname, sname, 0, pctx); +} + +static int asn1_print_fsname(BIO *out, int indent, +                             const char *fname, const char *sname, +                             const ASN1_PCTX *pctx) +{ +    static const char spaces[] = "                    "; +    static const int nspaces = sizeof(spaces) - 1; + +    while (indent > nspaces) { +        if (BIO_write(out, spaces, nspaces) != nspaces) +            return 0; +        indent -= nspaces; +    } +    if (BIO_write(out, spaces, indent) != indent) +        return 0; +    if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME) +        sname = NULL; +    if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME) +        fname = NULL; +    if (!sname && !fname) +        return 1; +    if (fname) { +        if (BIO_puts(out, fname) <= 0) +            return 0; +    } +    if (sname) { +        if (fname) { +            if (BIO_printf(out, " (%s)", sname) <= 0) +                return 0; +        } else { +            if (BIO_puts(out, sname) <= 0) +                return 0; +        } +    } +    if (BIO_write(out, ": ", 2) != 2) +        return 0; +    return 1; +} + +static int asn1_print_boolean(BIO *out, int boolval) +{ +    const char *str; +    switch (boolval) { +    case -1: +        str = "BOOL ABSENT"; +        break; + +    case 0: +        str = "FALSE"; +        break; + +    default: +        str = "TRUE"; +        break; + +    } + +    if (BIO_puts(out, str) <= 0) +        return 0; +    return 1; + +} + +static int asn1_print_integer(BIO *out, const ASN1_INTEGER *str) +{ +    char *s; +    int ret = 1; +    s = i2s_ASN1_INTEGER(NULL, str); +    if (s == NULL) +        return 0; +    if (BIO_puts(out, s) <= 0) +        ret = 0; +    OPENSSL_free(s); +    return ret; +} + +static int asn1_print_oid(BIO *out, const ASN1_OBJECT *oid) +{ +    char objbuf[80]; +    const char *ln; +    ln = OBJ_nid2ln(OBJ_obj2nid(oid)); +    if (!ln) +        ln = ""; +    OBJ_obj2txt(objbuf, sizeof(objbuf), oid, 1); +    if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0) +        return 0; +    return 1; +} + +static int asn1_print_obstring(BIO *out, const ASN1_STRING *str, int indent) +{ +    if (str->type == V_ASN1_BIT_STRING) { +        if (BIO_printf(out, " (%ld unused bits)\n", str->flags & 0x7) <= 0) +            return 0; +    } else if (BIO_puts(out, "\n") <= 0) +        return 0; +    if ((str->length > 0) +        && BIO_dump_indent(out, (const char *)str->data, str->length, +                           indent + 2) <= 0) +        return 0; +    return 1; +} + +static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld, +                                const ASN1_ITEM *it, int indent, +                                const char *fname, const char *sname, +                                const ASN1_PCTX *pctx) +{ +    long utype; +    ASN1_STRING *str; +    int ret = 1, needlf = 1; +    const char *pname; +    const ASN1_PRIMITIVE_FUNCS *pf; +    pf = it->funcs; +    if (!asn1_print_fsname(out, indent, fname, sname, pctx)) +        return 0; +    if (pf && pf->prim_print) +        return pf->prim_print(out, fld, it, indent, pctx); +    if (it->itype == ASN1_ITYPE_MSTRING) { +        str = (ASN1_STRING *)*fld; +        utype = str->type & ~V_ASN1_NEG; +    } else { +        utype = it->utype; +        if (utype == V_ASN1_BOOLEAN) +            str = NULL; +        else +            str = (ASN1_STRING *)*fld; +    } +    if (utype == V_ASN1_ANY) { +        ASN1_TYPE *atype = (ASN1_TYPE *)*fld; +        utype = atype->type; +        fld = &atype->value.asn1_value; +        str = (ASN1_STRING *)*fld; +        if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE) +            pname = NULL; +        else +            pname = ASN1_tag2str(utype); +    } else { +        if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE) +            pname = ASN1_tag2str(utype); +        else +            pname = NULL; +    } + +    if (utype == V_ASN1_NULL) { +        if (BIO_puts(out, "NULL\n") <= 0) +            return 0; +        return 1; +    } + +    if (pname) { +        if (BIO_puts(out, pname) <= 0) +            return 0; +        if (BIO_puts(out, ":") <= 0) +            return 0; +    } + +    switch (utype) { +    case V_ASN1_BOOLEAN: +        { +            int boolval = *(int *)fld; +            if (boolval == -1) +                boolval = it->size; +            ret = asn1_print_boolean(out, boolval); +        } +        break; + +    case V_ASN1_INTEGER: +    case V_ASN1_ENUMERATED: +        ret = asn1_print_integer(out, str); +        break; + +    case V_ASN1_UTCTIME: +        ret = ASN1_UTCTIME_print(out, str); +        break; + +    case V_ASN1_GENERALIZEDTIME: +        ret = ASN1_GENERALIZEDTIME_print(out, str); +        break; + +    case V_ASN1_OBJECT: +        ret = asn1_print_oid(out, (const ASN1_OBJECT *)*fld); +        break; + +    case V_ASN1_OCTET_STRING: +    case V_ASN1_BIT_STRING: +        ret = asn1_print_obstring(out, str, indent); +        needlf = 0; +        break; + +    case V_ASN1_SEQUENCE: +    case V_ASN1_SET: +    case V_ASN1_OTHER: +        if (BIO_puts(out, "\n") <= 0) +            return 0; +        if (ASN1_parse_dump(out, str->data, str->length, indent, 0) <= 0) +            ret = 0; +        needlf = 0; +        break; + +    default: +        ret = ASN1_STRING_print_ex(out, str, pctx->str_flags); + +    } +    if (!ret) +        return 0; +    if (needlf && BIO_puts(out, "\n") <= 0) +        return 0; +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_scn.c b/openssl-1.1.0h/crypto/asn1/tasn_scn.c new file mode 100644 index 0000000..e1df2cf --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_scn.c @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include "internal/cryptlib.h" +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include <openssl/buffer.h> +#include <openssl/err.h> +#include <openssl/x509v3.h> +#include "asn1_locl.h" + +/* + * General ASN1 structure recursive scanner: iterate through all fields + * passing details to a callback. + */ + +ASN1_SCTX *ASN1_SCTX_new(int (*scan_cb) (ASN1_SCTX *ctx)) +{ +    ASN1_SCTX *ret = OPENSSL_zalloc(sizeof(*ret)); + +    if (ret == NULL) { +        ASN1err(ASN1_F_ASN1_SCTX_NEW, ERR_R_MALLOC_FAILURE); +        return NULL; +    } +    ret->scan_cb = scan_cb; +    return ret; +} + +void ASN1_SCTX_free(ASN1_SCTX *p) +{ +    OPENSSL_free(p); +} + +const ASN1_ITEM *ASN1_SCTX_get_item(ASN1_SCTX *p) +{ +    return p->it; +} + +const ASN1_TEMPLATE *ASN1_SCTX_get_template(ASN1_SCTX *p) +{ +    return p->tt; +} + +unsigned long ASN1_SCTX_get_flags(ASN1_SCTX *p) +{ +    return p->flags; +} + +void ASN1_SCTX_set_app_data(ASN1_SCTX *p, void *data) +{ +    p->app_data = data; +} + +void *ASN1_SCTX_get_app_data(ASN1_SCTX *p) +{ +    return p->app_data; +} diff --git a/openssl-1.1.0h/crypto/asn1/tasn_typ.c b/openssl-1.1.0h/crypto/asn1/tasn_typ.c new file mode 100644 index 0000000..98d9879 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_typ.c @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> + +/* Declarations for string types */ + +#define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \ +    IMPLEMENT_ASN1_TYPE(sname) \ +    IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \ +sname *sname##_new(void) \ +{ \ +    return ASN1_STRING_type_new(V_##sname); \ +} \ +void sname##_free(sname *x) \ +{ \ +    ASN1_STRING_free(x); \ +} + +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_ENUMERATED) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BIT_STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTF8STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_PRINTABLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_T61STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_IA5STRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UTCTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_GENERALIZEDTIME) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_VISIBLESTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING) +IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING) + +IMPLEMENT_ASN1_TYPE(ASN1_NULL) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL) + +IMPLEMENT_ASN1_TYPE(ASN1_OBJECT) + +IMPLEMENT_ASN1_TYPE(ASN1_ANY) + +/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */ +IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE) + +IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE) + +/* Multistring types */ + +IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE) + +IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) + +IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING) +IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING) + +/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */ +IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1) +IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0) + +/* Special, OCTET STRING with indefinite length constructed support */ + +IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF) + +ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = +        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY) + +ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = +        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY) +ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY) + +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY) +IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY) diff --git a/openssl-1.1.0h/crypto/asn1/tasn_utl.c b/openssl-1.1.0h/crypto/asn1/tasn_utl.c new file mode 100644 index 0000000..f79d7d6 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/tasn_utl.c @@ -0,0 +1,240 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <string.h> +#include <internal/cryptlib.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/objects.h> +#include <openssl/err.h> +#include "asn1_locl.h" + +/* Utility functions for manipulating fields and offsets */ + +/* Add 'offset' to 'addr' */ +#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset) + +/* + * Given an ASN1_ITEM CHOICE type return the selector value + */ + +int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    int *sel = offset2ptr(*pval, it->utype); +    return *sel; +} + +/* + * Given an ASN1_ITEM CHOICE type set the selector value, return old value. + */ + +int asn1_set_choice_selector(ASN1_VALUE **pval, int value, +                             const ASN1_ITEM *it) +{ +    int *sel, ret; +    sel = offset2ptr(*pval, it->utype); +    ret = *sel; +    *sel = value; +    return ret; +} + +/* + * Do atomic reference counting. The value 'op' decides what to do. + * If it is +1 then the count is incremented. + * If |op| is 0, lock is initialised and count is set to 1. + * If |op| is -1, count is decremented and the return value is the current + * reference count or 0 if no reference count is active. + * It returns -1 on initialisation error. + * Used by ASN1_SEQUENCE construct of X509, X509_REQ, X509_CRL objects + */ +int asn1_do_lock(ASN1_VALUE **pval, int op, const ASN1_ITEM *it) +{ +    const ASN1_AUX *aux; +    int *lck, ret; +    CRYPTO_RWLOCK **lock; +    if ((it->itype != ASN1_ITYPE_SEQUENCE) +        && (it->itype != ASN1_ITYPE_NDEF_SEQUENCE)) +        return 0; +    aux = it->funcs; +    if (!aux || !(aux->flags & ASN1_AFLG_REFCOUNT)) +        return 0; +    lck = offset2ptr(*pval, aux->ref_offset); +    lock = offset2ptr(*pval, aux->ref_lock); +    if (op == 0) { +        *lck = 1; +        *lock = CRYPTO_THREAD_lock_new(); +        if (*lock == NULL) { +            ASN1err(ASN1_F_ASN1_DO_LOCK, ERR_R_MALLOC_FAILURE); +            return -1; +        } +        return 1; +    } +    if (CRYPTO_atomic_add(lck, op, &ret, *lock) < 0) +        return -1;  /* failed */ +#ifdef REF_PRINT +    fprintf(stderr, "%p:%4d:%s\n", it, *lck, it->sname); +#endif +    REF_ASSERT_ISNT(ret < 0); +    if (ret == 0) { +        CRYPTO_THREAD_lock_free(*lock); +        *lock = NULL; +    } +    return ret; +} + +static ASN1_ENCODING *asn1_get_enc_ptr(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    const ASN1_AUX *aux; +    if (!pval || !*pval) +        return NULL; +    aux = it->funcs; +    if (!aux || !(aux->flags & ASN1_AFLG_ENCODING)) +        return NULL; +    return offset2ptr(*pval, aux->enc_offset); +} + +void asn1_enc_init(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    ASN1_ENCODING *enc; +    enc = asn1_get_enc_ptr(pval, it); +    if (enc) { +        enc->enc = NULL; +        enc->len = 0; +        enc->modified = 1; +    } +} + +void asn1_enc_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    ASN1_ENCODING *enc; +    enc = asn1_get_enc_ptr(pval, it); +    if (enc) { +        OPENSSL_free(enc->enc); +        enc->enc = NULL; +        enc->len = 0; +        enc->modified = 1; +    } +} + +int asn1_enc_save(ASN1_VALUE **pval, const unsigned char *in, int inlen, +                  const ASN1_ITEM *it) +{ +    ASN1_ENCODING *enc; +    enc = asn1_get_enc_ptr(pval, it); +    if (!enc) +        return 1; + +    OPENSSL_free(enc->enc); +    enc->enc = OPENSSL_malloc(inlen); +    if (enc->enc == NULL) +        return 0; +    memcpy(enc->enc, in, inlen); +    enc->len = inlen; +    enc->modified = 0; + +    return 1; +} + +int asn1_enc_restore(int *len, unsigned char **out, ASN1_VALUE **pval, +                     const ASN1_ITEM *it) +{ +    ASN1_ENCODING *enc; +    enc = asn1_get_enc_ptr(pval, it); +    if (!enc || enc->modified) +        return 0; +    if (out) { +        memcpy(*out, enc->enc, enc->len); +        *out += enc->len; +    } +    if (len) +        *len = enc->len; +    return 1; +} + +/* Given an ASN1_TEMPLATE get a pointer to a field */ +ASN1_VALUE **asn1_get_field_ptr(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt) +{ +    ASN1_VALUE **pvaltmp; +    pvaltmp = offset2ptr(*pval, tt->offset); +    /* +     * NOTE for BOOLEAN types the field is just a plain int so we can't +     * return int **, so settle for (int *). +     */ +    return pvaltmp; +} + +/* + * Handle ANY DEFINED BY template, find the selector, look up the relevant + * ASN1_TEMPLATE in the table and return it. + */ + +const ASN1_TEMPLATE *asn1_do_adb(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt, +                                 int nullerr) +{ +    const ASN1_ADB *adb; +    const ASN1_ADB_TABLE *atbl; +    long selector; +    ASN1_VALUE **sfld; +    int i; +    if (!(tt->flags & ASN1_TFLG_ADB_MASK)) +        return tt; + +    /* Else ANY DEFINED BY ... get the table */ +    adb = ASN1_ADB_ptr(tt->item); + +    /* Get the selector field */ +    sfld = offset2ptr(*pval, adb->offset); + +    /* Check if NULL */ +    if (*sfld == NULL) { +        if (!adb->null_tt) +            goto err; +        return adb->null_tt; +    } + +    /* +     * Convert type to a long: NB: don't check for NID_undef here because it +     * might be a legitimate value in the table +     */ +    if (tt->flags & ASN1_TFLG_ADB_OID) +        selector = OBJ_obj2nid((ASN1_OBJECT *)*sfld); +    else +        selector = ASN1_INTEGER_get((ASN1_INTEGER *)*sfld); + +    /* Let application callback translate value */ +    if (adb->adb_cb != NULL && adb->adb_cb(&selector) == 0) { +        ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); +        return NULL; +    } + +    /* +     * Try to find matching entry in table Maybe should check application +     * types first to allow application override? Might also be useful to +     * have a flag which indicates table is sorted and we can do a binary +     * search. For now stick to a linear search. +     */ + +    for (atbl = adb->tbl, i = 0; i < adb->tblcount; i++, atbl++) +        if (atbl->value == selector) +            return &atbl->tt; + +    /* FIXME: need to search application table too */ + +    /* No match, return default type */ +    if (!adb->default_tt) +        goto err; +    return adb->default_tt; + + err: +    /* FIXME: should log the value or OID of unsupported type */ +    if (nullerr) +        ASN1err(ASN1_F_ASN1_DO_ADB, ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE); +    return NULL; +} diff --git a/openssl-1.1.0h/crypto/asn1/x_algor.c b/openssl-1.1.0h/crypto/asn1/x_algor.c new file mode 100644 index 0000000..72378db --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_algor.c @@ -0,0 +1,93 @@ +/* + * Copyright 1998-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stddef.h> +#include <openssl/x509.h> +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include "internal/evp_int.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) + +int X509_ALGOR_set0(X509_ALGOR *alg, 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) { +        ASN1_OBJECT_free(alg->algorithm); +        alg->algorithm = aobj; +    } +    if (ptype == 0) +        return 1; +    if (ptype == V_ASN1_UNDEF) { +        ASN1_TYPE_free(alg->parameter); +        alg->parameter = NULL; +    } else +        ASN1_TYPE_set(alg->parameter, ptype, pval); +    return 1; +} + +void X509_ALGOR_get0(const ASN1_OBJECT **paobj, int *pptype, +                     const void **ppval, const 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 (md->flags & 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); + +} + +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/openssl-1.1.0h/crypto/asn1/x_bignum.c b/openssl-1.1.0h/crypto/asn1/x_bignum.c new file mode 100644 index 0000000..da57e77 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_bignum.c @@ -0,0 +1,146 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/bn.h> + +/* + * Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER + * as a BIGNUM directly. Currently it ignores the sign which isn't a problem + * since all BIGNUMs used are non negative and anything that looks negative + * is normally due to an encoding error. + */ + +#define BN_SENSITIVE    1 + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                  const ASN1_ITEM *it); +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                  int utype, char *free_cont, const ASN1_ITEM *it); +static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                         int utype, char *free_cont, const ASN1_ITEM *it); +static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                    int indent, const ASN1_PCTX *pctx); + +static ASN1_PRIMITIVE_FUNCS bignum_pf = { +    NULL, 0, +    bn_new, +    bn_free, +    0, +    bn_c2i, +    bn_i2c, +    bn_print +}; + +static ASN1_PRIMITIVE_FUNCS cbignum_pf = { +    NULL, 0, +    bn_secure_new, +    bn_free, +    0, +    bn_secure_c2i, +    bn_i2c, +    bn_print +}; + +ASN1_ITEM_start(BIGNUM) +        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM" +ASN1_ITEM_end(BIGNUM) + +ASN1_ITEM_start(CBIGNUM) +        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &cbignum_pf, BN_SENSITIVE, "CBIGNUM" +ASN1_ITEM_end(CBIGNUM) + +static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *pval = (ASN1_VALUE *)BN_new(); +    if (*pval != NULL) +        return 1; +    else +        return 0; +} + +static int bn_secure_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *pval = (ASN1_VALUE *)BN_secure_new(); +    if (*pval != NULL) +        return 1; +    else +        return 0; +} + +static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    if (!*pval) +        return; +    if (it->size & BN_SENSITIVE) +        BN_clear_free((BIGNUM *)*pval); +    else +        BN_free((BIGNUM *)*pval); +    *pval = NULL; +} + +static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                  const ASN1_ITEM *it) +{ +    BIGNUM *bn; +    int pad; +    if (!*pval) +        return -1; +    bn = (BIGNUM *)*pval; +    /* If MSB set in an octet we need a padding byte */ +    if (BN_num_bits(bn) & 0x7) +        pad = 0; +    else +        pad = 1; +    if (cont) { +        if (pad) +            *cont++ = 0; +        BN_bn2bin(bn, cont); +    } +    return pad + BN_num_bytes(bn); +} + +static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                  int utype, char *free_cont, const ASN1_ITEM *it) +{ +    BIGNUM *bn; + +    if (*pval == NULL && !bn_new(pval, it)) +        return 0; +    bn = (BIGNUM *)*pval; +    if (!BN_bin2bn(cont, len, bn)) { +        bn_free(pval, it); +        return 0; +    } +    return 1; +} + +static int bn_secure_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                         int utype, char *free_cont, const ASN1_ITEM *it) +{ +    if (!*pval) +        bn_secure_new(pval, it); +    return bn_c2i(pval, cont, len, utype, free_cont, it); +} + +static int bn_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                    int indent, const ASN1_PCTX *pctx) +{ +    if (!BN_print(out, *(BIGNUM **)pval)) +        return 0; +    if (BIO_puts(out, "\n") <= 0) +        return 0; +    return 1; +} diff --git a/openssl-1.1.0h/crypto/asn1/x_info.c b/openssl-1.1.0h/crypto/asn1/x_info.c new file mode 100644 index 0000000..8d99f07 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_info.c @@ -0,0 +1,39 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/asn1.h> +#include <openssl/x509.h> + +X509_INFO *X509_INFO_new(void) +{ +    X509_INFO *ret; + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) { +        ASN1err(ASN1_F_X509_INFO_NEW, ERR_R_MALLOC_FAILURE); +        return NULL; +    } + +    return ret; +} + +void X509_INFO_free(X509_INFO *x) +{ +    if (x == NULL) +        return; + +    X509_free(x->x509); +    X509_CRL_free(x->crl); +    X509_PKEY_free(x->x_pkey); +    OPENSSL_free(x->enc_data); +    OPENSSL_free(x); +} diff --git a/openssl-1.1.0h/crypto/asn1/x_int64.c b/openssl-1.1.0h/crypto/asn1/x_int64.c new file mode 100644 index 0000000..4433167 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_int64.c @@ -0,0 +1,265 @@ +/* + * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include "internal/asn1t.h" +#include "internal/numbers.h" +#include <openssl/bn.h> +#include "asn1_locl.h" + +/* + * Custom primitive types for handling int32_t, int64_t, uint32_t, uint64_t. + * This converts between an ASN1_INTEGER and those types directly. + * This is preferred to using the LONG / ZLONG primitives. + */ + +/* + * We abuse the ASN1_ITEM fields |size| as a flags field + */ +#define INTxx_FLAG_ZERO_DEFAULT (1<<0) +#define INTxx_FLAG_SIGNED       (1<<1) + +static int uint64_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint64_t)); +    if (*pval == NULL) +        return 0; +    return 1; +} + +static void uint64_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    OPENSSL_free(*pval); +    *pval = NULL; +} + +static void uint64_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    **(uint64_t **)pval = 0; +} + +static int uint64_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                    const ASN1_ITEM *it) +{ +    uint64_t utmp; +    int neg = 0; +    /* this exists to bypass broken gcc optimization */ +    char *cp = (char *)*pval; + +    /* use memcpy, because we may not be uint64_t aligned */ +    memcpy(&utmp, cp, sizeof(utmp)); + +    if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT +        && utmp == 0) +        return -1; +    if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED +        && (int64_t)utmp < 0) { +        /* i2c_uint64_int() assumes positive values */ +        utmp = 0 - utmp; +        neg = 1; +    } + +    return i2c_uint64_int(cont, utmp, neg); +} + +static int uint64_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                    int utype, char *free_cont, const ASN1_ITEM *it) +{ +    uint64_t utmp = 0; +    char *cp; +    int neg = 0; + +    if (*pval == NULL && !uint64_new(pval, it)) +        return 0; + +    cp = (char *)*pval; +    if (!c2i_uint64_int(&utmp, &neg, &cont, len)) +        return 0; +    if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { +        ASN1err(ASN1_F_UINT64_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); +        return 0; +    } +    if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED +            && !neg && utmp > INT64_MAX) { +        ASN1err(ASN1_F_UINT64_C2I, ASN1_R_TOO_LARGE); +        return 0; +    } +    if (neg) +        /* c2i_uint64_int() returns positive values */ +        utmp = 0 - utmp; +    memcpy(cp, &utmp, sizeof(utmp)); +    return 1; +} + +static int uint64_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                        int indent, const ASN1_PCTX *pctx) +{ +    if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) +        return BIO_printf(out, "%"BIO_PRI64"d\n", **(int64_t **)pval); +    return BIO_printf(out, "%"BIO_PRI64"u\n", **(uint64_t **)pval); +} + +/* 32-bit variants */ + +static int uint32_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *pval = (ASN1_VALUE *)OPENSSL_zalloc(sizeof(uint32_t)); +    if (*pval == NULL) +        return 0; +    return 1; +} + +static void uint32_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    OPENSSL_free(*pval); +    *pval = NULL; +} + +static void uint32_clear(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    **(uint32_t **)pval = 0; +} + +static int uint32_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                    const ASN1_ITEM *it) +{ +    uint32_t utmp; +    int neg = 0; +    /* this exists to bypass broken gcc optimization */ +    char *cp = (char *)*pval; + +    /* use memcpy, because we may not be uint32_t aligned */ +    memcpy(&utmp, cp, sizeof(utmp)); + +    if ((it->size & INTxx_FLAG_ZERO_DEFAULT) == INTxx_FLAG_ZERO_DEFAULT +        && utmp == 0) +        return -1; +    if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED +        && (int32_t)utmp < 0) { +        /* i2c_uint64_int() assumes positive values */ +        utmp = 0 - utmp; +        neg = 1; +    } + +    return i2c_uint64_int(cont, (uint64_t)utmp, neg); +} + +/* + * Absolute value of INT32_MIN: we can't just use -INT32_MIN as it produces + * overflow warnings. + */ + +#define ABS_INT32_MIN ((uint32_t)INT32_MAX + 1) + +static int uint32_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                    int utype, char *free_cont, const ASN1_ITEM *it) +{ +    uint64_t utmp = 0; +    uint32_t utmp2 = 0; +    char *cp; +    int neg = 0; + +    if (*pval == NULL && !uint64_new(pval, it)) +        return 0; + +    cp = (char *)*pval; +    if (!c2i_uint64_int(&utmp, &neg, &cont, len)) +        return 0; +    if ((it->size & INTxx_FLAG_SIGNED) == 0 && neg) { +        ASN1err(ASN1_F_UINT32_C2I, ASN1_R_ILLEGAL_NEGATIVE_VALUE); +        return 0; +    } +    if (neg) { +        if (utmp > ABS_INT32_MIN) { +            ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_SMALL); +            return 0; +        } +        utmp = 0 - utmp; +    } else { +        if (((it->size & INTxx_FLAG_SIGNED) != 0 && utmp > INT32_MAX) +            || ((it->size & INTxx_FLAG_SIGNED) == 0 && utmp > UINT32_MAX)) { +            ASN1err(ASN1_F_UINT32_C2I, ASN1_R_TOO_LARGE); +            return 0; +        } +    } +    utmp2 = (uint32_t)utmp; +    memcpy(cp, &utmp2, sizeof(utmp2)); +    return 1; +} + +static int uint32_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                        int indent, const ASN1_PCTX *pctx) +{ +    if ((it->size & INTxx_FLAG_SIGNED) == INTxx_FLAG_SIGNED) +        return BIO_printf(out, "%d\n", **(int32_t **)pval); +    return BIO_printf(out, "%u\n", **(uint32_t **)pval); +} + + +/* Define the primitives themselves */ + +static ASN1_PRIMITIVE_FUNCS uint32_pf = { +    NULL, 0, +    uint32_new, +    uint32_free, +    uint32_clear, +    uint32_c2i, +    uint32_i2c, +    uint32_print +}; + +static ASN1_PRIMITIVE_FUNCS uint64_pf = { +    NULL, 0, +    uint64_new, +    uint64_free, +    uint64_clear, +    uint64_c2i, +    uint64_i2c, +    uint64_print +}; + +ASN1_ITEM_start(INT32) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, +    INTxx_FLAG_SIGNED, "INT32" +ASN1_ITEM_end(INT32) + +ASN1_ITEM_start(UINT32) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, 0, "UINT32" +ASN1_ITEM_end(UINT32) + +ASN1_ITEM_start(INT64) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, +    INTxx_FLAG_SIGNED, "INT64" +ASN1_ITEM_end(INT64) + +ASN1_ITEM_start(UINT64) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, 0, "UINT64" +ASN1_ITEM_end(UINT64) + +ASN1_ITEM_start(ZINT32) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, +    INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT32" +ASN1_ITEM_end(ZINT32) + +ASN1_ITEM_start(ZUINT32) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint32_pf, +    INTxx_FLAG_ZERO_DEFAULT, "ZUINT32" +ASN1_ITEM_end(ZUINT32) + +ASN1_ITEM_start(ZINT64) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, +    INTxx_FLAG_ZERO_DEFAULT|INTxx_FLAG_SIGNED, "ZINT64" +ASN1_ITEM_end(ZINT64) + +ASN1_ITEM_start(ZUINT64) +    ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &uint64_pf, +    INTxx_FLAG_ZERO_DEFAULT, "ZUINT64" +ASN1_ITEM_end(ZUINT64) + diff --git a/openssl-1.1.0h/crypto/asn1/x_long.c b/openssl-1.1.0h/crypto/asn1/x_long.c new file mode 100644 index 0000000..5895345 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_long.c @@ -0,0 +1,196 @@ +/* + * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> + +/* + * Custom primitive type for long handling. This converts between an + * ASN1_INTEGER and a long directly. + */ + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it); +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it); + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                    const ASN1_ITEM *it); +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                    int utype, char *free_cont, const ASN1_ITEM *it); +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                      int indent, const ASN1_PCTX *pctx); + +static ASN1_PRIMITIVE_FUNCS long_pf = { +    NULL, 0, +    long_new, +    long_free, +    long_free,                  /* Clear should set to initial value */ +    long_c2i, +    long_i2c, +    long_print +}; + +ASN1_ITEM_start(LONG) +        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG" +ASN1_ITEM_end(LONG) + +ASN1_ITEM_start(ZLONG) +        ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG" +ASN1_ITEM_end(ZLONG) + +static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *(long *)pval = it->size; +    return 1; +} + +static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it) +{ +    *(long *)pval = it->size; +} + +/* + * Originally BN_num_bits_word was called to perform this operation, but + * trouble is that there is no guarantee that sizeof(long) equals to + * sizeof(BN_ULONG). BN_ULONG is a configurable type that can be as wide + * as long, but also double or half... + */ +static int num_bits_ulong(unsigned long value) +{ +    size_t i; +    unsigned long ret = 0; + +    /* +     * It is argued that *on average* constant counter loop performs +     * not worse [if not better] than one with conditional break or +     * mask-n-table-lookup-style, because of branch misprediction +     * penalties. +     */ +    for (i = 0; i < sizeof(value) * 8; i++) { +        ret += (value != 0); +        value >>= 1; +    } + +    return (int)ret; +} + +static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, +                    const ASN1_ITEM *it) +{ +    long ltmp; +    unsigned long utmp, sign; +    int clen, pad, i; +    /* this exists to bypass broken gcc optimization */ +    char *cp = (char *)pval; + +    /* use memcpy, because we may not be long aligned */ +    memcpy(<mp, cp, sizeof(long)); + +    if (ltmp == it->size) +        return -1; +    /* +     * Convert the long to positive: we subtract one if negative so we can +     * cleanly handle the padding if only the MSB of the leading octet is +     * set. +     */ +    if (ltmp < 0) { +        sign = 0xff; +        utmp = 0 - (unsigned long)ltmp - 1; +    } else { +        sign = 0; +        utmp = ltmp; +    } +    clen = num_bits_ulong(utmp); +    /* If MSB of leading octet set we need to pad */ +    if (!(clen & 0x7)) +        pad = 1; +    else +        pad = 0; + +    /* Convert number of bits to number of octets */ +    clen = (clen + 7) >> 3; + +    if (cont != NULL) { +        if (pad) +            *cont++ = (unsigned char)sign; +        for (i = clen - 1; i >= 0; i--) { +            cont[i] = (unsigned char)(utmp ^ sign); +            utmp >>= 8; +        } +    } +    return clen + pad; +} + +static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, +                    int utype, char *free_cont, const ASN1_ITEM *it) +{ +    int i; +    long ltmp; +    unsigned long utmp = 0, sign = 0x100; +    char *cp = (char *)pval; + +    if (len > 1) { +        /* +         * Check possible pad byte.  Worst case, we're skipping past actual +         * content, but since that's only with 0x00 and 0xff and we set neg +         * accordingly, the result will be correct in the end anyway. +         */ +        switch (cont[0]) { +        case 0xff: +            cont++; +            len--; +            sign = 0xff; +            break; +        case 0: +            cont++; +            len--; +            sign = 0; +            break; +        } +    } +    if (len > (int)sizeof(long)) { +        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); +        return 0; +    } + +    if (sign == 0x100) { +        /* Is it negative? */ +        if (len && (cont[0] & 0x80)) +            sign = 0xff; +        else +            sign = 0; +    } else if (((sign ^ cont[0]) & 0x80) == 0) { /* same sign bit? */ +        ASN1err(ASN1_F_LONG_C2I, ASN1_R_ILLEGAL_PADDING); +        return 0; +    } +    utmp = 0; +    for (i = 0; i < len; i++) { +        utmp <<= 8; +        utmp |= cont[i] ^ sign; +    } +    ltmp = (long)utmp; +    if (ltmp < 0) { +        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); +        return 0; +    } +    if (sign) +        ltmp = -ltmp - 1; +    if (ltmp == it->size) { +        ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); +        return 0; +    } +    memcpy(cp, <mp, sizeof(long)); +    return 1; +} + +static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, +                      int indent, const ASN1_PCTX *pctx) +{ +    return BIO_printf(out, "%ld\n", *(long *)pval); +} diff --git a/openssl-1.1.0h/crypto/asn1/x_pkey.c b/openssl-1.1.0h/crypto/asn1/x_pkey.c new file mode 100644 index 0000000..593049f --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_pkey.c @@ -0,0 +1,47 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +X509_PKEY *X509_PKEY_new(void) +{ +    X509_PKEY *ret = NULL; + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) +        goto err; + +    ret->enc_algor = X509_ALGOR_new(); +    ret->enc_pkey = ASN1_OCTET_STRING_new(); +    if (ret->enc_algor == NULL || ret->enc_pkey == NULL) +        goto err; + +    return ret; +err: +    X509_PKEY_free(ret); +    ASN1err(ASN1_F_X509_PKEY_NEW, ERR_R_MALLOC_FAILURE); +    return NULL; +} + +void X509_PKEY_free(X509_PKEY *x) +{ +    if (x == NULL) +        return; + +    X509_ALGOR_free(x->enc_algor); +    ASN1_OCTET_STRING_free(x->enc_pkey); +    EVP_PKEY_free(x->dec_pkey); +    if (x->key_free) +        OPENSSL_free(x->key_data); +    OPENSSL_free(x); +} diff --git a/openssl-1.1.0h/crypto/asn1/x_sig.c b/openssl-1.1.0h/crypto/asn1/x_sig.c new file mode 100644 index 0000000..e465cf2 --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_sig.c @@ -0,0 +1,39 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/asn1t.h> +#include <openssl/x509.h> +#include "internal/x509_int.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) + +void X509_SIG_get0(const X509_SIG *sig, const X509_ALGOR **palg, +                   const ASN1_OCTET_STRING **pdigest) +{ +    if (palg) +        *palg = sig->algor; +    if (pdigest) +        *pdigest = sig->digest; +} + +void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg, +                   ASN1_OCTET_STRING **pdigest) +{ +    if (palg) +        *palg = sig->algor; +    if (pdigest) +        *pdigest = sig->digest; +} diff --git a/openssl-1.1.0h/crypto/asn1/x_spki.c b/openssl-1.1.0h/crypto/asn1/x_spki.c new file mode 100644 index 0000000..c45400b --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_spki.c @@ -0,0 +1,33 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + + /* +  * This module was send to me my Pat Richards <patr@x509.com> who wrote it. +  * It is under my Copyright with his permission +  */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#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_EMBED(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/openssl-1.1.0h/crypto/asn1/x_val.c b/openssl-1.1.0h/crypto/asn1/x_val.c new file mode 100644 index 0000000..d1f1d3b --- /dev/null +++ b/openssl-1.1.0h/crypto/asn1/x_val.c @@ -0,0 +1,20 @@ +/* + * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License").  You may not use + * this file except in compliance with the License.  You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <stdio.h> +#include "internal/cryptlib.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) | 
