diff options
Diffstat (limited to 'openssl-1.1.0h/crypto/evp')
60 files changed, 15899 insertions, 0 deletions
diff --git a/openssl-1.1.0h/crypto/evp/bio_b64.c b/openssl-1.1.0h/crypto/evp/bio_b64.c new file mode 100644 index 0000000..a86e8db --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/bio_b64.c @@ -0,0 +1,551 @@ +/* + * 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 <errno.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/evp.h> +#include "internal/bio.h" + +static int b64_write(BIO *h, const char *buf, int num); +static int b64_read(BIO *h, char *buf, int size); +static int b64_puts(BIO *h, const char *str); +/* + * static int b64_gets(BIO *h, char *str, int size); + */ +static long b64_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int b64_new(BIO *h); +static int b64_free(BIO *data); +static long b64_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); +#define B64_BLOCK_SIZE  1024 +#define B64_BLOCK_SIZE2 768 +#define B64_NONE        0 +#define B64_ENCODE      1 +#define B64_DECODE      2 + +typedef struct b64_struct { +    /* +     * BIO *bio; moved to the BIO structure +     */ +    int buf_len; +    int buf_off; +    int tmp_len;                /* used to find the start when decoding */ +    int tmp_nl;                 /* If true, scan until '\n' */ +    int encode; +    int start;                  /* have we started decoding yet? */ +    int cont;                   /* <= 0 when finished */ +    EVP_ENCODE_CTX *base64; +    char buf[EVP_ENCODE_LENGTH(B64_BLOCK_SIZE) + 10]; +    char tmp[B64_BLOCK_SIZE]; +} BIO_B64_CTX; + +static const BIO_METHOD methods_b64 = { +    BIO_TYPE_BASE64, +    "base64 encoding", +    b64_write, +    b64_read, +    b64_puts, +    NULL,                       /* b64_gets, */ +    b64_ctrl, +    b64_new, +    b64_free, +    b64_callback_ctrl, +}; + + +const BIO_METHOD *BIO_f_base64(void) +{ +    return &methods_b64; +} + +static int b64_new(BIO *bi) +{ +    BIO_B64_CTX *ctx; + +    ctx = OPENSSL_zalloc(sizeof(*ctx)); +    if (ctx == NULL) +        return 0; + +    ctx->cont = 1; +    ctx->start = 1; +    ctx->base64 = EVP_ENCODE_CTX_new(); +    if (ctx->base64 == NULL) { +        OPENSSL_free(ctx); +        return 0; +    } + +    BIO_set_data(bi, ctx); +    BIO_set_init(bi, 1); + +    return 1; +} + +static int b64_free(BIO *a) +{ +    BIO_B64_CTX *ctx; +    if (a == NULL) +        return 0; + +    ctx = BIO_get_data(a); +    if (ctx == NULL) +        return 0; + +    EVP_ENCODE_CTX_free(ctx->base64); +    OPENSSL_free(ctx); +    BIO_set_data(a, NULL); +    BIO_set_init(a, 0); + +    return 1; +} + +static int b64_read(BIO *b, char *out, int outl) +{ +    int ret = 0, i, ii, j, k, x, n, num, ret_code = 0; +    BIO_B64_CTX *ctx; +    unsigned char *p, *q; +    BIO *next; + +    if (out == NULL) +        return (0); +    ctx = (BIO_B64_CTX *)BIO_get_data(b); + +    next = BIO_next(b); +    if ((ctx == NULL) || (next == NULL)) +        return 0; + +    BIO_clear_retry_flags(b); + +    if (ctx->encode != B64_DECODE) { +        ctx->encode = B64_DECODE; +        ctx->buf_len = 0; +        ctx->buf_off = 0; +        ctx->tmp_len = 0; +        EVP_DecodeInit(ctx->base64); +    } + +    /* First check if there are bytes decoded/encoded */ +    if (ctx->buf_len > 0) { +        OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +        i = ctx->buf_len - ctx->buf_off; +        if (i > outl) +            i = outl; +        OPENSSL_assert(ctx->buf_off + i < (int)sizeof(ctx->buf)); +        memcpy(out, &(ctx->buf[ctx->buf_off]), i); +        ret = i; +        out += i; +        outl -= i; +        ctx->buf_off += i; +        if (ctx->buf_len == ctx->buf_off) { +            ctx->buf_len = 0; +            ctx->buf_off = 0; +        } +    } + +    /* +     * At this point, we have room of outl bytes and an empty buffer, so we +     * should read in some more. +     */ + +    ret_code = 0; +    while (outl > 0) { +        if (ctx->cont <= 0) +            break; + +        i = BIO_read(next, &(ctx->tmp[ctx->tmp_len]), +                     B64_BLOCK_SIZE - ctx->tmp_len); + +        if (i <= 0) { +            ret_code = i; + +            /* Should we continue next time we are called? */ +            if (!BIO_should_retry(next)) { +                ctx->cont = i; +                /* If buffer empty break */ +                if (ctx->tmp_len == 0) +                    break; +                /* Fall through and process what we have */ +                else +                    i = 0; +            } +            /* else we retry and add more data to buffer */ +            else +                break; +        } +        i += ctx->tmp_len; +        ctx->tmp_len = i; + +        /* +         * We need to scan, a line at a time until we have a valid line if we +         * are starting. +         */ +        if (ctx->start && (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL)) { +            /* ctx->start=1; */ +            ctx->tmp_len = 0; +        } else if (ctx->start) { +            q = p = (unsigned char *)ctx->tmp; +            num = 0; +            for (j = 0; j < i; j++) { +                if (*(q++) != '\n') +                    continue; + +                /* +                 * due to a previous very long line, we need to keep on +                 * scanning for a '\n' before we even start looking for +                 * base64 encoded stuff. +                 */ +                if (ctx->tmp_nl) { +                    p = q; +                    ctx->tmp_nl = 0; +                    continue; +                } + +                k = EVP_DecodeUpdate(ctx->base64, +                                     (unsigned char *)ctx->buf, +                                     &num, p, q - p); +                if ((k <= 0) && (num == 0) && (ctx->start)) +                    EVP_DecodeInit(ctx->base64); +                else { +                    if (p != (unsigned char *) +                        &(ctx->tmp[0])) { +                        i -= (p - (unsigned char *) +                              &(ctx->tmp[0])); +                        for (x = 0; x < i; x++) +                            ctx->tmp[x] = p[x]; +                    } +                    EVP_DecodeInit(ctx->base64); +                    ctx->start = 0; +                    break; +                } +                p = q; +            } + +            /* we fell off the end without starting */ +            if ((j == i) && (num == 0)) { +                /* +                 * Is this is one long chunk?, if so, keep on reading until a +                 * new line. +                 */ +                if (p == (unsigned char *)&(ctx->tmp[0])) { +                    /* Check buffer full */ +                    if (i == B64_BLOCK_SIZE) { +                        ctx->tmp_nl = 1; +                        ctx->tmp_len = 0; +                    } +                } else if (p != q) { /* finished on a '\n' */ +                    n = q - p; +                    for (ii = 0; ii < n; ii++) +                        ctx->tmp[ii] = p[ii]; +                    ctx->tmp_len = n; +                } +                /* else finished on a '\n' */ +                continue; +            } else { +                ctx->tmp_len = 0; +            } +        } else if ((i < B64_BLOCK_SIZE) && (ctx->cont > 0)) { +            /* +             * If buffer isn't full and we can retry then restart to read in +             * more data. +             */ +            continue; +        } + +        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { +            int z, jj; + +            jj = i & ~3;        /* process per 4 */ +            z = EVP_DecodeBlock((unsigned char *)ctx->buf, +                                (unsigned char *)ctx->tmp, jj); +            if (jj > 2) { +                if (ctx->tmp[jj - 1] == '=') { +                    z--; +                    if (ctx->tmp[jj - 2] == '=') +                        z--; +                } +            } +            /* +             * z is now number of output bytes and jj is the number consumed +             */ +            if (jj != i) { +                memmove(ctx->tmp, &ctx->tmp[jj], i - jj); +                ctx->tmp_len = i - jj; +            } +            ctx->buf_len = 0; +            if (z > 0) { +                ctx->buf_len = z; +            } +            i = z; +        } else { +            i = EVP_DecodeUpdate(ctx->base64, +                                 (unsigned char *)ctx->buf, &ctx->buf_len, +                                 (unsigned char *)ctx->tmp, i); +            ctx->tmp_len = 0; +        } +        /* +         * If eof or an error was signalled, then the condition +         * 'ctx->cont <= 0' will prevent b64_read() from reading +         * more data on subsequent calls. This assignment was +         * deleted accidentally in commit 5562cfaca4f3. +         */ +        ctx->cont = i; + +        ctx->buf_off = 0; +        if (i < 0) { +            ret_code = 0; +            ctx->buf_len = 0; +            break; +        } + +        if (ctx->buf_len <= outl) +            i = ctx->buf_len; +        else +            i = outl; + +        memcpy(out, ctx->buf, i); +        ret += i; +        ctx->buf_off = i; +        if (ctx->buf_off == ctx->buf_len) { +            ctx->buf_len = 0; +            ctx->buf_off = 0; +        } +        outl -= i; +        out += i; +    } +    /* BIO_clear_retry_flags(b); */ +    BIO_copy_next_retry(b); +    return ((ret == 0) ? ret_code : ret); +} + +static int b64_write(BIO *b, const char *in, int inl) +{ +    int ret = 0; +    int n; +    int i; +    BIO_B64_CTX *ctx; +    BIO *next; + +    ctx = (BIO_B64_CTX *)BIO_get_data(b); +    next = BIO_next(b); +    if ((ctx == NULL) || (next == NULL)) +        return 0; + +    BIO_clear_retry_flags(b); + +    if (ctx->encode != B64_ENCODE) { +        ctx->encode = B64_ENCODE; +        ctx->buf_len = 0; +        ctx->buf_off = 0; +        ctx->tmp_len = 0; +        EVP_EncodeInit(ctx->base64); +    } + +    OPENSSL_assert(ctx->buf_off < (int)sizeof(ctx->buf)); +    OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); +    OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +    n = ctx->buf_len - ctx->buf_off; +    while (n > 0) { +        i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); +        if (i <= 0) { +            BIO_copy_next_retry(b); +            return (i); +        } +        OPENSSL_assert(i <= n); +        ctx->buf_off += i; +        OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); +        OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +        n -= i; +    } +    /* at this point all pending data has been written */ +    ctx->buf_off = 0; +    ctx->buf_len = 0; + +    if ((in == NULL) || (inl <= 0)) +        return (0); + +    while (inl > 0) { +        n = (inl > B64_BLOCK_SIZE) ? B64_BLOCK_SIZE : inl; + +        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { +            if (ctx->tmp_len > 0) { +                OPENSSL_assert(ctx->tmp_len <= 3); +                n = 3 - ctx->tmp_len; +                /* +                 * There's a theoretical possibility for this +                 */ +                if (n > inl) +                    n = inl; +                memcpy(&(ctx->tmp[ctx->tmp_len]), in, n); +                ctx->tmp_len += n; +                ret += n; +                if (ctx->tmp_len < 3) +                    break; +                ctx->buf_len = +                    EVP_EncodeBlock((unsigned char *)ctx->buf, +                                    (unsigned char *)ctx->tmp, ctx->tmp_len); +                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); +                OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +                /* +                 * Since we're now done using the temporary buffer, the +                 * length should be 0'd +                 */ +                ctx->tmp_len = 0; +            } else { +                if (n < 3) { +                    memcpy(ctx->tmp, in, n); +                    ctx->tmp_len = n; +                    ret += n; +                    break; +                } +                n -= n % 3; +                ctx->buf_len = +                    EVP_EncodeBlock((unsigned char *)ctx->buf, +                                    (const unsigned char *)in, n); +                OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); +                OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +                ret += n; +            } +        } else { +            if (!EVP_EncodeUpdate(ctx->base64, +                                 (unsigned char *)ctx->buf, &ctx->buf_len, +                                 (unsigned char *)in, n)) +                return ((ret == 0) ? -1 : ret); +            OPENSSL_assert(ctx->buf_len <= (int)sizeof(ctx->buf)); +            OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +            ret += n; +        } +        inl -= n; +        in += n; + +        ctx->buf_off = 0; +        n = ctx->buf_len; +        while (n > 0) { +            i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); +            if (i <= 0) { +                BIO_copy_next_retry(b); +                return ((ret == 0) ? i : ret); +            } +            OPENSSL_assert(i <= n); +            n -= i; +            ctx->buf_off += i; +            OPENSSL_assert(ctx->buf_off <= (int)sizeof(ctx->buf)); +            OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +        } +        ctx->buf_len = 0; +        ctx->buf_off = 0; +    } +    return (ret); +} + +static long b64_ctrl(BIO *b, int cmd, long num, void *ptr) +{ +    BIO_B64_CTX *ctx; +    long ret = 1; +    int i; +    BIO *next; + +    ctx = (BIO_B64_CTX *)BIO_get_data(b); +    next = BIO_next(b); +    if ((ctx == NULL) || (next == NULL)) +        return 0; + +    switch (cmd) { +    case BIO_CTRL_RESET: +        ctx->cont = 1; +        ctx->start = 1; +        ctx->encode = B64_NONE; +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_EOF:         /* More to read */ +        if (ctx->cont <= 0) +            ret = 1; +        else +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_WPENDING:    /* More to write in buffer */ +        OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +        ret = ctx->buf_len - ctx->buf_off; +        if ((ret == 0) && (ctx->encode != B64_NONE) +            && (EVP_ENCODE_CTX_num(ctx->base64) != 0)) +            ret = 1; +        else if (ret <= 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_PENDING:     /* More to read in buffer */ +        OPENSSL_assert(ctx->buf_len >= ctx->buf_off); +        ret = ctx->buf_len - ctx->buf_off; +        if (ret <= 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_FLUSH: +        /* do a final write */ + again: +        while (ctx->buf_len != ctx->buf_off) { +            i = b64_write(b, NULL, 0); +            if (i < 0) +                return i; +        } +        if (BIO_get_flags(b) & BIO_FLAGS_BASE64_NO_NL) { +            if (ctx->tmp_len != 0) { +                ctx->buf_len = EVP_EncodeBlock((unsigned char *)ctx->buf, +                                               (unsigned char *)ctx->tmp, +                                               ctx->tmp_len); +                ctx->buf_off = 0; +                ctx->tmp_len = 0; +                goto again; +            } +        } else if (ctx->encode != B64_NONE +                   && EVP_ENCODE_CTX_num(ctx->base64) != 0) { +            ctx->buf_off = 0; +            EVP_EncodeFinal(ctx->base64, +                            (unsigned char *)ctx->buf, &(ctx->buf_len)); +            /* push out the bytes */ +            goto again; +        } +        /* Finally flush the underlying BIO */ +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; + +    case BIO_C_DO_STATE_MACHINE: +        BIO_clear_retry_flags(b); +        ret = BIO_ctrl(next, cmd, num, ptr); +        BIO_copy_next_retry(b); +        break; + +    case BIO_CTRL_DUP: +        break; +    case BIO_CTRL_INFO: +    case BIO_CTRL_GET: +    case BIO_CTRL_SET: +    default: +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    } +    return ret; +} + +static long b64_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ +    long ret = 1; +    BIO *next = BIO_next(b); + +    if (next == NULL) +        return 0; +    switch (cmd) { +    default: +        ret = BIO_callback_ctrl(next, cmd, fp); +        break; +    } +    return (ret); +} + +static int b64_puts(BIO *b, const char *str) +{ +    return b64_write(b, str, strlen(str)); +} diff --git a/openssl-1.1.0h/crypto/evp/bio_enc.c b/openssl-1.1.0h/crypto/evp/bio_enc.c new file mode 100644 index 0000000..e62d1df --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/bio_enc.c @@ -0,0 +1,450 @@ +/* + * 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 <errno.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/evp.h> +#include "internal/bio.h" + +static int enc_write(BIO *h, const char *buf, int num); +static int enc_read(BIO *h, char *buf, int size); +/* + * static int enc_puts(BIO *h, const char *str); + */ +/* + * static int enc_gets(BIO *h, char *str, int size); + */ +static long enc_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int enc_new(BIO *h); +static int enc_free(BIO *data); +static long enc_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fps); +#define ENC_BLOCK_SIZE  (1024*4) +#define ENC_MIN_CHUNK   (256) +#define BUF_OFFSET      (ENC_MIN_CHUNK + EVP_MAX_BLOCK_LENGTH) + +typedef struct enc_struct { +    int buf_len; +    int buf_off; +    int cont;                   /* <= 0 when finished */ +    int finished; +    int ok;                     /* bad decrypt */ +    EVP_CIPHER_CTX *cipher; +    unsigned char *read_start, *read_end; +    /* +     * buf is larger than ENC_BLOCK_SIZE because EVP_DecryptUpdate can return +     * up to a block more data than is presented to it +     */ +    unsigned char buf[BUF_OFFSET + ENC_BLOCK_SIZE]; +} BIO_ENC_CTX; + +static const BIO_METHOD methods_enc = { +    BIO_TYPE_CIPHER, +    "cipher", +    enc_write, +    enc_read, +    NULL,                       /* enc_puts, */ +    NULL,                       /* enc_gets, */ +    enc_ctrl, +    enc_new, +    enc_free, +    enc_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_cipher(void) +{ +    return (&methods_enc); +} + +static int enc_new(BIO *bi) +{ +    BIO_ENC_CTX *ctx; + +    ctx = OPENSSL_zalloc(sizeof(*ctx)); +    if (ctx == NULL) +        return 0; + +    ctx->cipher = EVP_CIPHER_CTX_new(); +    if (ctx->cipher == NULL) { +        OPENSSL_free(ctx); +        return 0; +    } +    ctx->cont = 1; +    ctx->ok = 1; +    ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); +    BIO_set_data(bi, ctx); +    BIO_set_init(bi, 1); + +    return 1; +} + +static int enc_free(BIO *a) +{ +    BIO_ENC_CTX *b; + +    if (a == NULL) +        return 0; + +    b = BIO_get_data(a); +    if (b == NULL) +        return 0; + +    EVP_CIPHER_CTX_free(b->cipher); +    OPENSSL_clear_free(b, sizeof(BIO_ENC_CTX)); +    BIO_set_data(a, NULL); +    BIO_set_init(a, 0); + +    return 1; +} + +static int enc_read(BIO *b, char *out, int outl) +{ +    int ret = 0, i, blocksize; +    BIO_ENC_CTX *ctx; +    BIO *next; + +    if (out == NULL) +        return (0); +    ctx = BIO_get_data(b); + +    next = BIO_next(b); +    if ((ctx == NULL) || (next == NULL)) +        return 0; + +    /* First check if there are bytes decoded/encoded */ +    if (ctx->buf_len > 0) { +        i = ctx->buf_len - ctx->buf_off; +        if (i > outl) +            i = outl; +        memcpy(out, &(ctx->buf[ctx->buf_off]), i); +        ret = i; +        out += i; +        outl -= i; +        ctx->buf_off += i; +        if (ctx->buf_len == ctx->buf_off) { +            ctx->buf_len = 0; +            ctx->buf_off = 0; +        } +    } + +    blocksize = EVP_CIPHER_CTX_block_size(ctx->cipher); +    if (blocksize == 1) +        blocksize = 0; + +    /* +     * At this point, we have room of outl bytes and an empty buffer, so we +     * should read in some more. +     */ + +    while (outl > 0) { +        if (ctx->cont <= 0) +            break; + +        if (ctx->read_start == ctx->read_end) { /* time to read more data */ +            ctx->read_end = ctx->read_start = &(ctx->buf[BUF_OFFSET]); +            i = BIO_read(next, ctx->read_start, ENC_BLOCK_SIZE); +            if (i > 0) +                ctx->read_end += i; +        } else { +            i = ctx->read_end - ctx->read_start; +        } + +        if (i <= 0) { +            /* Should be continue next time we are called? */ +            if (!BIO_should_retry(next)) { +                ctx->cont = i; +                i = EVP_CipherFinal_ex(ctx->cipher, +                                       ctx->buf, &(ctx->buf_len)); +                ctx->ok = i; +                ctx->buf_off = 0; +            } else { +                ret = (ret == 0) ? i : ret; +                break; +            } +        } else { +            if (outl > ENC_MIN_CHUNK) { +                /* +                 * Depending on flags block cipher decrypt can write +                 * one extra block and then back off, i.e. output buffer +                 * has to accommodate extra block... +                 */ +                int j = outl - blocksize, buf_len; + +                if (!EVP_CipherUpdate(ctx->cipher, +                                      (unsigned char *)out, &buf_len, +                                      ctx->read_start, i > j ? j : i)) { +                    BIO_clear_retry_flags(b); +                    return 0; +                } +                ret += buf_len; +                out += buf_len; +                outl -= buf_len; + +                if ((i -= j) <= 0) { +                    ctx->read_start = ctx->read_end; +                    continue; +                } +                ctx->read_start += j; +            } +            if (i > ENC_MIN_CHUNK) +                i = ENC_MIN_CHUNK; +            if (!EVP_CipherUpdate(ctx->cipher, +                                  ctx->buf, &ctx->buf_len, +                                  ctx->read_start, i)) { +                BIO_clear_retry_flags(b); +                ctx->ok = 0; +                return 0; +            } +            ctx->read_start += i; +            ctx->cont = 1; +            /* +             * Note: it is possible for EVP_CipherUpdate to decrypt zero +             * bytes because this is or looks like the final block: if this +             * happens we should retry and either read more data or decrypt +             * the final block +             */ +            if (ctx->buf_len == 0) +                continue; +        } + +        if (ctx->buf_len <= outl) +            i = ctx->buf_len; +        else +            i = outl; +        if (i <= 0) +            break; +        memcpy(out, ctx->buf, i); +        ret += i; +        ctx->buf_off = i; +        outl -= i; +        out += i; +    } + +    BIO_clear_retry_flags(b); +    BIO_copy_next_retry(b); +    return ((ret == 0) ? ctx->cont : ret); +} + +static int enc_write(BIO *b, const char *in, int inl) +{ +    int ret = 0, n, i; +    BIO_ENC_CTX *ctx; +    BIO *next; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); +    if ((ctx == NULL) || (next == NULL)) +        return 0; + +    ret = inl; + +    BIO_clear_retry_flags(b); +    n = ctx->buf_len - ctx->buf_off; +    while (n > 0) { +        i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); +        if (i <= 0) { +            BIO_copy_next_retry(b); +            return (i); +        } +        ctx->buf_off += i; +        n -= i; +    } +    /* at this point all pending data has been written */ + +    if ((in == NULL) || (inl <= 0)) +        return (0); + +    ctx->buf_off = 0; +    while (inl > 0) { +        n = (inl > ENC_BLOCK_SIZE) ? ENC_BLOCK_SIZE : inl; +        if (!EVP_CipherUpdate(ctx->cipher, +                              ctx->buf, &ctx->buf_len, +                              (const unsigned char *)in, n)) { +            BIO_clear_retry_flags(b); +            ctx->ok = 0; +            return 0; +        } +        inl -= n; +        in += n; + +        ctx->buf_off = 0; +        n = ctx->buf_len; +        while (n > 0) { +            i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); +            if (i <= 0) { +                BIO_copy_next_retry(b); +                return (ret == inl) ? i : ret - inl; +            } +            n -= i; +            ctx->buf_off += i; +        } +        ctx->buf_len = 0; +        ctx->buf_off = 0; +    } +    BIO_copy_next_retry(b); +    return (ret); +} + +static long enc_ctrl(BIO *b, int cmd, long num, void *ptr) +{ +    BIO *dbio; +    BIO_ENC_CTX *ctx, *dctx; +    long ret = 1; +    int i; +    EVP_CIPHER_CTX **c_ctx; +    BIO *next; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); +    if (ctx == NULL) +        return 0; + +    switch (cmd) { +    case BIO_CTRL_RESET: +        ctx->ok = 1; +        ctx->finished = 0; +        if (!EVP_CipherInit_ex(ctx->cipher, NULL, NULL, NULL, NULL, +                               EVP_CIPHER_CTX_encrypting(ctx->cipher))) +            return 0; +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_EOF:         /* More to read */ +        if (ctx->cont <= 0) +            ret = 1; +        else +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_WPENDING: +        ret = ctx->buf_len - ctx->buf_off; +        if (ret <= 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_PENDING:     /* More to read in buffer */ +        ret = ctx->buf_len - ctx->buf_off; +        if (ret <= 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_FLUSH: +        /* do a final write */ + again: +        while (ctx->buf_len != ctx->buf_off) { +            i = enc_write(b, NULL, 0); +            if (i < 0) +                return i; +        } + +        if (!ctx->finished) { +            ctx->finished = 1; +            ctx->buf_off = 0; +            ret = EVP_CipherFinal_ex(ctx->cipher, +                                     (unsigned char *)ctx->buf, +                                     &(ctx->buf_len)); +            ctx->ok = (int)ret; +            if (ret <= 0) +                break; + +            /* push out the bytes */ +            goto again; +        } + +        /* Finally flush the underlying BIO */ +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_C_GET_CIPHER_STATUS: +        ret = (long)ctx->ok; +        break; +    case BIO_C_DO_STATE_MACHINE: +        BIO_clear_retry_flags(b); +        ret = BIO_ctrl(next, cmd, num, ptr); +        BIO_copy_next_retry(b); +        break; +    case BIO_C_GET_CIPHER_CTX: +        c_ctx = (EVP_CIPHER_CTX **)ptr; +        *c_ctx = ctx->cipher; +        BIO_set_init(b, 1); +        break; +    case BIO_CTRL_DUP: +        dbio = (BIO *)ptr; +        dctx = BIO_get_data(dbio); +        dctx->cipher = EVP_CIPHER_CTX_new(); +        if (dctx->cipher == NULL) +            return 0; +        ret = EVP_CIPHER_CTX_copy(dctx->cipher, ctx->cipher); +        if (ret) +            BIO_set_init(dbio, 1); +        break; +    default: +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    } +    return (ret); +} + +static long enc_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ +    long ret = 1; +    BIO *next = BIO_next(b); + +    if (next == NULL) +        return (0); +    switch (cmd) { +    default: +        ret = BIO_callback_ctrl(next, cmd, fp); +        break; +    } +    return (ret); +} + +/*- +void BIO_set_cipher_ctx(b,c) +BIO *b; +EVP_CIPHER_ctx *c; +        { +        if (b == NULL) return; + +        if ((b->callback != NULL) && +                (b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,0L) <= 0)) +                return; + +        b->init=1; +        ctx=(BIO_ENC_CTX *)b->ptr; +        memcpy(ctx->cipher,c,sizeof(EVP_CIPHER_CTX)); + +        if (b->callback != NULL) +                b->callback(b,BIO_CB_CTRL,(char *)c,BIO_CTRL_SET,e,1L); +        } +*/ + +int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k, +                   const unsigned char *i, int e) +{ +    BIO_ENC_CTX *ctx; +    long (*callback) (struct bio_st *, int, const char *, int, long, long); + +    ctx = BIO_get_data(b); +    if (ctx == NULL) +        return 0; + +    callback = BIO_get_callback(b); + +    if ((callback != NULL) && +            (callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, +                      0L) <= 0)) +        return 0; + +    BIO_set_init(b, 1); + +    if (!EVP_CipherInit_ex(ctx->cipher, c, NULL, k, i, e)) +        return 0; + +    if (callback != NULL) +        return callback(b, BIO_CB_CTRL, (const char *)c, BIO_CTRL_SET, e, 1L); +    return 1; +} diff --git a/openssl-1.1.0h/crypto/evp/bio_md.c b/openssl-1.1.0h/crypto/evp/bio_md.c new file mode 100644 index 0000000..2f0f283 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/bio_md.c @@ -0,0 +1,232 @@ +/* + * 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 <errno.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include <openssl/evp.h> +#include "internal/evp_int.h" +#include "evp_locl.h" +#include "internal/bio.h" + +/* + * BIO_put and BIO_get both add to the digest, BIO_gets returns the digest + */ + +static int md_write(BIO *h, char const *buf, int num); +static int md_read(BIO *h, char *buf, int size); +/* + * static int md_puts(BIO *h, const char *str); + */ +static int md_gets(BIO *h, char *str, int size); +static long md_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int md_new(BIO *h); +static int md_free(BIO *data); +static long md_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static const BIO_METHOD methods_md = { +    BIO_TYPE_MD, +    "message digest", +    md_write, +    md_read, +    NULL,                       /* md_puts, */ +    md_gets, +    md_ctrl, +    md_new, +    md_free, +    md_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_md(void) +{ +    return (&methods_md); +} + +static int md_new(BIO *bi) +{ +    EVP_MD_CTX *ctx; + +    ctx = EVP_MD_CTX_new(); +    if (ctx == NULL) +        return (0); + +    BIO_set_init(bi, 1); +    BIO_set_data(bi, ctx); + +    return 1; +} + +static int md_free(BIO *a) +{ +    if (a == NULL) +        return (0); +    EVP_MD_CTX_free(BIO_get_data(a)); +    BIO_set_data(a, NULL); +    BIO_set_init(a, 0); + +    return 1; +} + +static int md_read(BIO *b, char *out, int outl) +{ +    int ret = 0; +    EVP_MD_CTX *ctx; +    BIO *next; + +    if (out == NULL) +        return (0); + +    ctx = BIO_get_data(b); +    next = BIO_next(b); + +    if ((ctx == NULL) || (next == NULL)) +        return (0); + +    ret = BIO_read(next, out, outl); +    if (BIO_get_init(b)) { +        if (ret > 0) { +            if (EVP_DigestUpdate(ctx, (unsigned char *)out, +                                 (unsigned int)ret) <= 0) +                return (-1); +        } +    } +    BIO_clear_retry_flags(b); +    BIO_copy_next_retry(b); +    return (ret); +} + +static int md_write(BIO *b, const char *in, int inl) +{ +    int ret = 0; +    EVP_MD_CTX *ctx; +    BIO *next; + +    if ((in == NULL) || (inl <= 0)) +        return 0; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); +    if ((ctx != NULL) && (next != NULL)) +        ret = BIO_write(next, in, inl); + +    if (BIO_get_init(b)) { +        if (ret > 0) { +            if (!EVP_DigestUpdate(ctx, (const unsigned char *)in, +                                  (unsigned int)ret)) { +                BIO_clear_retry_flags(b); +                return 0; +            } +        } +    } +    if (next != NULL) { +        BIO_clear_retry_flags(b); +        BIO_copy_next_retry(b); +    } +    return ret; +} + +static long md_ctrl(BIO *b, int cmd, long num, void *ptr) +{ +    EVP_MD_CTX *ctx, *dctx, **pctx; +    const EVP_MD **ppmd; +    EVP_MD *md; +    long ret = 1; +    BIO *dbio, *next; + + +    ctx = BIO_get_data(b); +    next = BIO_next(b); + +    switch (cmd) { +    case BIO_CTRL_RESET: +        if (BIO_get_init(b)) +            ret = EVP_DigestInit_ex(ctx, ctx->digest, NULL); +        else +            ret = 0; +        if (ret > 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_C_GET_MD: +        if (BIO_get_init(b)) { +            ppmd = ptr; +            *ppmd = ctx->digest; +        } else +            ret = 0; +        break; +    case BIO_C_GET_MD_CTX: +        pctx = ptr; +        *pctx = ctx; +        BIO_set_init(b, 1); +        break; +    case BIO_C_SET_MD_CTX: +        if (BIO_get_init(b)) +            BIO_set_data(b, ptr); +        else +            ret = 0; +        break; +    case BIO_C_DO_STATE_MACHINE: +        BIO_clear_retry_flags(b); +        ret = BIO_ctrl(next, cmd, num, ptr); +        BIO_copy_next_retry(b); +        break; + +    case BIO_C_SET_MD: +        md = ptr; +        ret = EVP_DigestInit_ex(ctx, md, NULL); +        if (ret > 0) +            BIO_set_init(b, 1); +        break; +    case BIO_CTRL_DUP: +        dbio = ptr; +        dctx = BIO_get_data(dbio); +        if (!EVP_MD_CTX_copy_ex(dctx, ctx)) +            return 0; +        BIO_set_init(b, 1); +        break; +    default: +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    } +    return (ret); +} + +static long md_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ +    long ret = 1; +    BIO *next; + +    next = BIO_next(b); + +    if (next == NULL) +        return 0; + +    switch (cmd) { +    default: +        ret = BIO_callback_ctrl(next, cmd, fp); +        break; +    } +    return (ret); +} + +static int md_gets(BIO *bp, char *buf, int size) +{ +    EVP_MD_CTX *ctx; +    unsigned int ret; + +    ctx = BIO_get_data(bp); + +    if (size < ctx->digest->md_size) +        return 0; + +    if (EVP_DigestFinal_ex(ctx, (unsigned char *)buf, &ret) <= 0) +        return -1; + +    return ((int)ret); +} diff --git a/openssl-1.1.0h/crypto/evp/bio_ok.c b/openssl-1.1.0h/crypto/evp/bio_ok.c new file mode 100644 index 0000000..b156e62 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/bio_ok.c @@ -0,0 +1,605 @@ +/* + * 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 + */ + +/*- +        From: Arne Ansper <arne@cyber.ee> + +        Why BIO_f_reliable? + +        I wrote function which took BIO* as argument, read data from it +        and processed it. Then I wanted to store the input file in +        encrypted form. OK I pushed BIO_f_cipher to the BIO stack +        and everything was OK. BUT if user types wrong password +        BIO_f_cipher outputs only garbage and my function crashes. Yes +        I can and I should fix my function, but BIO_f_cipher is +        easy way to add encryption support to many existing applications +        and it's hard to debug and fix them all. + +        So I wanted another BIO which would catch the incorrect passwords and +        file damages which cause garbage on BIO_f_cipher's output. + +        The easy way is to push the BIO_f_md and save the checksum at +        the end of the file. However there are several problems with this +        approach: + +        1) you must somehow separate checksum from actual data. +        2) you need lot's of memory when reading the file, because you +        must read to the end of the file and verify the checksum before +        letting the application to read the data. + +        BIO_f_reliable tries to solve both problems, so that you can +        read and write arbitrary long streams using only fixed amount +        of memory. + +        BIO_f_reliable splits data stream into blocks. Each block is prefixed +        with it's length and suffixed with it's digest. So you need only +        several Kbytes of memory to buffer single block before verifying +        it's digest. + +        BIO_f_reliable goes further and adds several important capabilities: + +        1) the digest of the block is computed over the whole stream +        -- so nobody can rearrange the blocks or remove or replace them. + +        2) to detect invalid passwords right at the start BIO_f_reliable +        adds special prefix to the stream. In order to avoid known plain-text +        attacks this prefix is generated as follows: + +                *) digest is initialized with random seed instead of +                standardized one. +                *) same seed is written to output +                *) well-known text is then hashed and the output +                of the digest is also written to output. + +        reader can now read the seed from stream, hash the same string +        and then compare the digest output. + +        Bad things: BIO_f_reliable knows what's going on in EVP_Digest. I +        initially wrote and tested this code on x86 machine and wrote the +        digests out in machine-dependent order :( There are people using +        this code and I cannot change this easily without making existing +        data files unreadable. + +*/ + +#include <stdio.h> +#include <errno.h> +#include <assert.h> +#include "internal/cryptlib.h" +#include <openssl/buffer.h> +#include "internal/bio.h" +#include <openssl/evp.h> +#include <openssl/rand.h> +#include "internal/evp_int.h" + +static int ok_write(BIO *h, const char *buf, int num); +static int ok_read(BIO *h, char *buf, int size); +static long ok_ctrl(BIO *h, int cmd, long arg1, void *arg2); +static int ok_new(BIO *h); +static int ok_free(BIO *data); +static long ok_callback_ctrl(BIO *h, int cmd, BIO_info_cb *fp); + +static __owur int sig_out(BIO *b); +static __owur int sig_in(BIO *b); +static __owur int block_out(BIO *b); +static __owur int block_in(BIO *b); +#define OK_BLOCK_SIZE   (1024*4) +#define OK_BLOCK_BLOCK  4 +#define IOBS            (OK_BLOCK_SIZE+ OK_BLOCK_BLOCK+ 3*EVP_MAX_MD_SIZE) +#define WELLKNOWN "The quick brown fox jumped over the lazy dog's back." + +typedef struct ok_struct { +    size_t buf_len; +    size_t buf_off; +    size_t buf_len_save; +    size_t buf_off_save; +    int cont;                   /* <= 0 when finished */ +    int finished; +    EVP_MD_CTX *md; +    int blockout;               /* output block is ready */ +    int sigio;                  /* must process signature */ +    unsigned char buf[IOBS]; +} BIO_OK_CTX; + +static const BIO_METHOD methods_ok = { +    BIO_TYPE_CIPHER, +    "reliable", +    ok_write, +    ok_read, +    NULL,                       /* ok_puts, */ +    NULL,                       /* ok_gets, */ +    ok_ctrl, +    ok_new, +    ok_free, +    ok_callback_ctrl, +}; + +const BIO_METHOD *BIO_f_reliable(void) +{ +    return (&methods_ok); +} + +static int ok_new(BIO *bi) +{ +    BIO_OK_CTX *ctx; + +    ctx = OPENSSL_zalloc(sizeof(*ctx)); +    if (ctx == NULL) +        return 0; + +    ctx->cont = 1; +    ctx->sigio = 1; +    ctx->md = EVP_MD_CTX_new(); +    if (ctx->md == NULL) { +        OPENSSL_free(ctx); +        return 0; +    } +    BIO_set_init(bi, 0); +    BIO_set_data(bi, ctx); + +    return 1; +} + +static int ok_free(BIO *a) +{ +    BIO_OK_CTX *ctx; + +    if (a == NULL) +        return 0; + +    ctx = BIO_get_data(a); + +    EVP_MD_CTX_free(ctx->md); +    OPENSSL_clear_free(ctx, sizeof(BIO_OK_CTX)); +    BIO_set_data(a, NULL); +    BIO_set_init(a, 0); + +    return 1; +} + +static int ok_read(BIO *b, char *out, int outl) +{ +    int ret = 0, i, n; +    BIO_OK_CTX *ctx; +    BIO *next; + +    if (out == NULL) +        return 0; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); + +    if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0)) +        return 0; + +    while (outl > 0) { + +        /* copy clean bytes to output buffer */ +        if (ctx->blockout) { +            i = ctx->buf_len - ctx->buf_off; +            if (i > outl) +                i = outl; +            memcpy(out, &(ctx->buf[ctx->buf_off]), i); +            ret += i; +            out += i; +            outl -= i; +            ctx->buf_off += i; + +            /* all clean bytes are out */ +            if (ctx->buf_len == ctx->buf_off) { +                ctx->buf_off = 0; + +                /* +                 * copy start of the next block into proper place +                 */ +                if (ctx->buf_len_save - ctx->buf_off_save > 0) { +                    ctx->buf_len = ctx->buf_len_save - ctx->buf_off_save; +                    memmove(ctx->buf, &(ctx->buf[ctx->buf_off_save]), +                            ctx->buf_len); +                } else { +                    ctx->buf_len = 0; +                } +                ctx->blockout = 0; +            } +        } + +        /* output buffer full -- cancel */ +        if (outl == 0) +            break; + +        /* no clean bytes in buffer -- fill it */ +        n = IOBS - ctx->buf_len; +        i = BIO_read(next, &(ctx->buf[ctx->buf_len]), n); + +        if (i <= 0) +            break;              /* nothing new */ + +        ctx->buf_len += i; + +        /* no signature yet -- check if we got one */ +        if (ctx->sigio == 1) { +            if (!sig_in(b)) { +                BIO_clear_retry_flags(b); +                return 0; +            } +        } + +        /* signature ok -- check if we got block */ +        if (ctx->sigio == 0) { +            if (!block_in(b)) { +                BIO_clear_retry_flags(b); +                return 0; +            } +        } + +        /* invalid block -- cancel */ +        if (ctx->cont <= 0) +            break; + +    } + +    BIO_clear_retry_flags(b); +    BIO_copy_next_retry(b); +    return ret; +} + +static int ok_write(BIO *b, const char *in, int inl) +{ +    int ret = 0, n, i; +    BIO_OK_CTX *ctx; +    BIO *next; + +    if (inl <= 0) +        return inl; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); +    ret = inl; + +    if ((ctx == NULL) || (next == NULL) || (BIO_get_init(b) == 0)) +        return (0); + +    if (ctx->sigio && !sig_out(b)) +        return 0; + +    do { +        BIO_clear_retry_flags(b); +        n = ctx->buf_len - ctx->buf_off; +        while (ctx->blockout && n > 0) { +            i = BIO_write(next, &(ctx->buf[ctx->buf_off]), n); +            if (i <= 0) { +                BIO_copy_next_retry(b); +                if (!BIO_should_retry(b)) +                    ctx->cont = 0; +                return (i); +            } +            ctx->buf_off += i; +            n -= i; +        } + +        /* at this point all pending data has been written */ +        ctx->blockout = 0; +        if (ctx->buf_len == ctx->buf_off) { +            ctx->buf_len = OK_BLOCK_BLOCK; +            ctx->buf_off = 0; +        } + +        if ((in == NULL) || (inl <= 0)) +            return (0); + +        n = (inl + ctx->buf_len > OK_BLOCK_SIZE + OK_BLOCK_BLOCK) ? +            (int)(OK_BLOCK_SIZE + OK_BLOCK_BLOCK - ctx->buf_len) : inl; + +        memcpy(&ctx->buf[ctx->buf_len], in, n); +        ctx->buf_len += n; +        inl -= n; +        in += n; + +        if (ctx->buf_len >= OK_BLOCK_SIZE + OK_BLOCK_BLOCK) { +            if (!block_out(b)) { +                BIO_clear_retry_flags(b); +                return 0; +            } +        } +    } while (inl > 0); + +    BIO_clear_retry_flags(b); +    BIO_copy_next_retry(b); +    return (ret); +} + +static long ok_ctrl(BIO *b, int cmd, long num, void *ptr) +{ +    BIO_OK_CTX *ctx; +    EVP_MD *md; +    const EVP_MD **ppmd; +    long ret = 1; +    int i; +    BIO *next; + +    ctx = BIO_get_data(b); +    next = BIO_next(b); + +    switch (cmd) { +    case BIO_CTRL_RESET: +        ctx->buf_len = 0; +        ctx->buf_off = 0; +        ctx->buf_len_save = 0; +        ctx->buf_off_save = 0; +        ctx->cont = 1; +        ctx->finished = 0; +        ctx->blockout = 0; +        ctx->sigio = 1; +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_EOF:         /* More to read */ +        if (ctx->cont <= 0) +            ret = 1; +        else +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_PENDING:     /* More to read in buffer */ +    case BIO_CTRL_WPENDING:    /* More to read in buffer */ +        ret = ctx->blockout ? ctx->buf_len - ctx->buf_off : 0; +        if (ret <= 0) +            ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_CTRL_FLUSH: +        /* do a final write */ +        if (ctx->blockout == 0) +            if (!block_out(b)) +                return 0; + +        while (ctx->blockout) { +            i = ok_write(b, NULL, 0); +            if (i < 0) { +                ret = i; +                break; +            } +        } + +        ctx->finished = 1; +        ctx->buf_off = ctx->buf_len = 0; +        ctx->cont = (int)ret; + +        /* Finally flush the underlying BIO */ +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    case BIO_C_DO_STATE_MACHINE: +        BIO_clear_retry_flags(b); +        ret = BIO_ctrl(next, cmd, num, ptr); +        BIO_copy_next_retry(b); +        break; +    case BIO_CTRL_INFO: +        ret = (long)ctx->cont; +        break; +    case BIO_C_SET_MD: +        md = ptr; +        if (!EVP_DigestInit_ex(ctx->md, md, NULL)) +            return 0; +        BIO_set_init(b, 1); +        break; +    case BIO_C_GET_MD: +        if (BIO_get_init(b)) { +            ppmd = ptr; +            *ppmd = EVP_MD_CTX_md(ctx->md); +        } else +            ret = 0; +        break; +    default: +        ret = BIO_ctrl(next, cmd, num, ptr); +        break; +    } +    return ret; +} + +static long ok_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) +{ +    long ret = 1; +    BIO *next; + +    next = BIO_next(b); + +    if (next == NULL) +        return 0; + +    switch (cmd) { +    default: +        ret = BIO_callback_ctrl(next, cmd, fp); +        break; +    } + +    return ret; +} + +static void longswap(void *_ptr, size_t len) +{ +    const union { +        long one; +        char little; +    } is_endian = { +        1 +    }; + +    if (is_endian.little) { +        size_t i; +        unsigned char *p = _ptr, c; + +        for (i = 0; i < len; i += 4) { +            c = p[0], p[0] = p[3], p[3] = c; +            c = p[1], p[1] = p[2], p[2] = c; +        } +    } +} + +static int sig_out(BIO *b) +{ +    BIO_OK_CTX *ctx; +    EVP_MD_CTX *md; +    const EVP_MD *digest; +    int md_size; +    void *md_data; + +    ctx = BIO_get_data(b); +    md = ctx->md; +    digest = EVP_MD_CTX_md(md); +    md_size = EVP_MD_size(digest); +    md_data = EVP_MD_CTX_md_data(md); + +    if (ctx->buf_len + 2 * md_size > OK_BLOCK_SIZE) +        return 1; + +    if (!EVP_DigestInit_ex(md, digest, NULL)) +        goto berr; +    /* +     * FIXME: there's absolutely no guarantee this makes any sense at all, +     * particularly now EVP_MD_CTX has been restructured. +     */ +    if (RAND_bytes(md_data, md_size) <= 0) +        goto berr; +    memcpy(&(ctx->buf[ctx->buf_len]), md_data, md_size); +    longswap(&(ctx->buf[ctx->buf_len]), md_size); +    ctx->buf_len += md_size; + +    if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) +        goto berr; +    if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) +        goto berr; +    ctx->buf_len += md_size; +    ctx->blockout = 1; +    ctx->sigio = 0; +    return 1; + berr: +    BIO_clear_retry_flags(b); +    return 0; +} + +static int sig_in(BIO *b) +{ +    BIO_OK_CTX *ctx; +    EVP_MD_CTX *md; +    unsigned char tmp[EVP_MAX_MD_SIZE]; +    int ret = 0; +    const EVP_MD *digest; +    int md_size; +    void *md_data; + +    ctx = BIO_get_data(b); +    md = ctx->md; +    digest = EVP_MD_CTX_md(md); +    md_size = EVP_MD_size(digest); +    md_data = EVP_MD_CTX_md_data(md); + +    if ((int)(ctx->buf_len - ctx->buf_off) < 2 * md_size) +        return 1; + +    if (!EVP_DigestInit_ex(md, digest, NULL)) +        goto berr; +    memcpy(md_data, &(ctx->buf[ctx->buf_off]), md_size); +    longswap(md_data, md_size); +    ctx->buf_off += md_size; + +    if (!EVP_DigestUpdate(md, WELLKNOWN, strlen(WELLKNOWN))) +        goto berr; +    if (!EVP_DigestFinal_ex(md, tmp, NULL)) +        goto berr; +    ret = memcmp(&(ctx->buf[ctx->buf_off]), tmp, md_size) == 0; +    ctx->buf_off += md_size; +    if (ret == 1) { +        ctx->sigio = 0; +        if (ctx->buf_len != ctx->buf_off) { +            memmove(ctx->buf, &(ctx->buf[ctx->buf_off]), +                    ctx->buf_len - ctx->buf_off); +        } +        ctx->buf_len -= ctx->buf_off; +        ctx->buf_off = 0; +    } else { +        ctx->cont = 0; +    } +    return 1; + berr: +    BIO_clear_retry_flags(b); +    return 0; +} + +static int block_out(BIO *b) +{ +    BIO_OK_CTX *ctx; +    EVP_MD_CTX *md; +    unsigned long tl; +    const EVP_MD *digest; +    int md_size; + +    ctx = BIO_get_data(b); +    md = ctx->md; +    digest = EVP_MD_CTX_md(md); +    md_size = EVP_MD_size(digest); + +    tl = ctx->buf_len - OK_BLOCK_BLOCK; +    ctx->buf[0] = (unsigned char)(tl >> 24); +    ctx->buf[1] = (unsigned char)(tl >> 16); +    ctx->buf[2] = (unsigned char)(tl >> 8); +    ctx->buf[3] = (unsigned char)(tl); +    if (!EVP_DigestUpdate(md, +                          (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) +        goto berr; +    if (!EVP_DigestFinal_ex(md, &(ctx->buf[ctx->buf_len]), NULL)) +        goto berr; +    ctx->buf_len += md_size; +    ctx->blockout = 1; +    return 1; + berr: +    BIO_clear_retry_flags(b); +    return 0; +} + +static int block_in(BIO *b) +{ +    BIO_OK_CTX *ctx; +    EVP_MD_CTX *md; +    unsigned long tl = 0; +    unsigned char tmp[EVP_MAX_MD_SIZE]; +    int md_size; + +    ctx = BIO_get_data(b); +    md = ctx->md; +    md_size = EVP_MD_size(EVP_MD_CTX_md(md)); + +    assert(sizeof(tl) >= OK_BLOCK_BLOCK); /* always true */ +    tl = ctx->buf[0]; +    tl <<= 8; +    tl |= ctx->buf[1]; +    tl <<= 8; +    tl |= ctx->buf[2]; +    tl <<= 8; +    tl |= ctx->buf[3]; + +    if (ctx->buf_len < tl + OK_BLOCK_BLOCK + md_size) +        return 1; + +    if (!EVP_DigestUpdate(md, +                          (unsigned char *)&(ctx->buf[OK_BLOCK_BLOCK]), tl)) +        goto berr; +    if (!EVP_DigestFinal_ex(md, tmp, NULL)) +        goto berr; +    if (memcmp(&(ctx->buf[tl + OK_BLOCK_BLOCK]), tmp, md_size) == 0) { +        /* there might be parts from next block lurking around ! */ +        ctx->buf_off_save = tl + OK_BLOCK_BLOCK + md_size; +        ctx->buf_len_save = ctx->buf_len; +        ctx->buf_off = OK_BLOCK_BLOCK; +        ctx->buf_len = tl + OK_BLOCK_BLOCK; +        ctx->blockout = 1; +    } else { +        ctx->cont = 0; +    } +    return 1; + berr: +    BIO_clear_retry_flags(b); +    return 0; +} diff --git a/openssl-1.1.0h/crypto/evp/build.info b/openssl-1.1.0h/crypto/evp/build.info new file mode 100644 index 0000000..bf633dc --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/build.info @@ -0,0 +1,22 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ +        encode.c digest.c evp_enc.c evp_key.c evp_cnf.c \ +        e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\ +        e_rc4.c e_aes.c names.c e_seed.c \ +        e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \ +        m_null.c m_md2.c m_md4.c m_md5.c m_sha1.c m_wp.c \ +        m_md5_sha1.c m_mdc2.c m_ripemd.c \ +        p_open.c p_seal.c p_sign.c p_verify.c p_lib.c p_enc.c p_dec.c \ +        bio_md.c bio_b64.c bio_enc.c evp_err.c e_null.c \ +        c_allc.c c_alld.c evp_lib.c bio_ok.c \ +        evp_pkey.c evp_pbe.c p5_crpt.c p5_crpt2.c scrypt.c \ +        e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ +        e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ +        e_chacha20_poly1305.c cmeth_lib.c + +INCLUDE[e_aes.o]=.. ../modes +INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes +INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes +INCLUDE[e_camellia.o]=.. ../modes +INCLUDE[e_des.o]=.. +INCLUDE[e_des3.o]=.. diff --git a/openssl-1.1.0h/crypto/evp/c_allc.c b/openssl-1.1.0h/crypto/evp/c_allc.c new file mode 100644 index 0000000..6ed31ed --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/c_allc.c @@ -0,0 +1,220 @@ +/* + * 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 <internal/evp_int.h> +#include <openssl/pkcs12.h> +#include <openssl/objects.h> + +void openssl_add_all_ciphers_int(void) +{ + +#ifndef OPENSSL_NO_DES +    EVP_add_cipher(EVP_des_cfb()); +    EVP_add_cipher(EVP_des_cfb1()); +    EVP_add_cipher(EVP_des_cfb8()); +    EVP_add_cipher(EVP_des_ede_cfb()); +    EVP_add_cipher(EVP_des_ede3_cfb()); +    EVP_add_cipher(EVP_des_ede3_cfb1()); +    EVP_add_cipher(EVP_des_ede3_cfb8()); + +    EVP_add_cipher(EVP_des_ofb()); +    EVP_add_cipher(EVP_des_ede_ofb()); +    EVP_add_cipher(EVP_des_ede3_ofb()); + +    EVP_add_cipher(EVP_desx_cbc()); +    EVP_add_cipher_alias(SN_desx_cbc, "DESX"); +    EVP_add_cipher_alias(SN_desx_cbc, "desx"); + +    EVP_add_cipher(EVP_des_cbc()); +    EVP_add_cipher_alias(SN_des_cbc, "DES"); +    EVP_add_cipher_alias(SN_des_cbc, "des"); +    EVP_add_cipher(EVP_des_ede_cbc()); +    EVP_add_cipher(EVP_des_ede3_cbc()); +    EVP_add_cipher_alias(SN_des_ede3_cbc, "DES3"); +    EVP_add_cipher_alias(SN_des_ede3_cbc, "des3"); + +    EVP_add_cipher(EVP_des_ecb()); +    EVP_add_cipher(EVP_des_ede()); +    EVP_add_cipher_alias(SN_des_ede_ecb, "DES-EDE-ECB"); +    EVP_add_cipher_alias(SN_des_ede_ecb, "des-ede-ecb"); +    EVP_add_cipher(EVP_des_ede3()); +    EVP_add_cipher_alias(SN_des_ede3_ecb, "DES-EDE3-ECB"); +    EVP_add_cipher_alias(SN_des_ede3_ecb, "des-ede3-ecb"); +    EVP_add_cipher(EVP_des_ede3_wrap()); +    EVP_add_cipher_alias(SN_id_smime_alg_CMS3DESwrap, "des3-wrap"); +#endif + +#ifndef OPENSSL_NO_RC4 +    EVP_add_cipher(EVP_rc4()); +    EVP_add_cipher(EVP_rc4_40()); +# ifndef OPENSSL_NO_MD5 +    EVP_add_cipher(EVP_rc4_hmac_md5()); +# endif +#endif + +#ifndef OPENSSL_NO_IDEA +    EVP_add_cipher(EVP_idea_ecb()); +    EVP_add_cipher(EVP_idea_cfb()); +    EVP_add_cipher(EVP_idea_ofb()); +    EVP_add_cipher(EVP_idea_cbc()); +    EVP_add_cipher_alias(SN_idea_cbc, "IDEA"); +    EVP_add_cipher_alias(SN_idea_cbc, "idea"); +#endif + +#ifndef OPENSSL_NO_SEED +    EVP_add_cipher(EVP_seed_ecb()); +    EVP_add_cipher(EVP_seed_cfb()); +    EVP_add_cipher(EVP_seed_ofb()); +    EVP_add_cipher(EVP_seed_cbc()); +    EVP_add_cipher_alias(SN_seed_cbc, "SEED"); +    EVP_add_cipher_alias(SN_seed_cbc, "seed"); +#endif + +#ifndef OPENSSL_NO_RC2 +    EVP_add_cipher(EVP_rc2_ecb()); +    EVP_add_cipher(EVP_rc2_cfb()); +    EVP_add_cipher(EVP_rc2_ofb()); +    EVP_add_cipher(EVP_rc2_cbc()); +    EVP_add_cipher(EVP_rc2_40_cbc()); +    EVP_add_cipher(EVP_rc2_64_cbc()); +    EVP_add_cipher_alias(SN_rc2_cbc, "RC2"); +    EVP_add_cipher_alias(SN_rc2_cbc, "rc2"); +    EVP_add_cipher_alias(SN_rc2_cbc, "rc2-128"); +    EVP_add_cipher_alias(SN_rc2_64_cbc, "rc2-64"); +    EVP_add_cipher_alias(SN_rc2_40_cbc, "rc2-40"); +#endif + +#ifndef OPENSSL_NO_BF +    EVP_add_cipher(EVP_bf_ecb()); +    EVP_add_cipher(EVP_bf_cfb()); +    EVP_add_cipher(EVP_bf_ofb()); +    EVP_add_cipher(EVP_bf_cbc()); +    EVP_add_cipher_alias(SN_bf_cbc, "BF"); +    EVP_add_cipher_alias(SN_bf_cbc, "bf"); +    EVP_add_cipher_alias(SN_bf_cbc, "blowfish"); +#endif + +#ifndef OPENSSL_NO_CAST +    EVP_add_cipher(EVP_cast5_ecb()); +    EVP_add_cipher(EVP_cast5_cfb()); +    EVP_add_cipher(EVP_cast5_ofb()); +    EVP_add_cipher(EVP_cast5_cbc()); +    EVP_add_cipher_alias(SN_cast5_cbc, "CAST"); +    EVP_add_cipher_alias(SN_cast5_cbc, "cast"); +    EVP_add_cipher_alias(SN_cast5_cbc, "CAST-cbc"); +    EVP_add_cipher_alias(SN_cast5_cbc, "cast-cbc"); +#endif + +#ifndef OPENSSL_NO_RC5 +    EVP_add_cipher(EVP_rc5_32_12_16_ecb()); +    EVP_add_cipher(EVP_rc5_32_12_16_cfb()); +    EVP_add_cipher(EVP_rc5_32_12_16_ofb()); +    EVP_add_cipher(EVP_rc5_32_12_16_cbc()); +    EVP_add_cipher_alias(SN_rc5_cbc, "rc5"); +    EVP_add_cipher_alias(SN_rc5_cbc, "RC5"); +#endif + +    EVP_add_cipher(EVP_aes_128_ecb()); +    EVP_add_cipher(EVP_aes_128_cbc()); +    EVP_add_cipher(EVP_aes_128_cfb()); +    EVP_add_cipher(EVP_aes_128_cfb1()); +    EVP_add_cipher(EVP_aes_128_cfb8()); +    EVP_add_cipher(EVP_aes_128_ofb()); +    EVP_add_cipher(EVP_aes_128_ctr()); +    EVP_add_cipher(EVP_aes_128_gcm()); +#ifndef OPENSSL_NO_OCB +    EVP_add_cipher(EVP_aes_128_ocb()); +#endif +    EVP_add_cipher(EVP_aes_128_xts()); +    EVP_add_cipher(EVP_aes_128_ccm()); +    EVP_add_cipher(EVP_aes_128_wrap()); +    EVP_add_cipher_alias(SN_id_aes128_wrap, "aes128-wrap"); +    EVP_add_cipher(EVP_aes_128_wrap_pad()); +    EVP_add_cipher_alias(SN_aes_128_cbc, "AES128"); +    EVP_add_cipher_alias(SN_aes_128_cbc, "aes128"); +    EVP_add_cipher(EVP_aes_192_ecb()); +    EVP_add_cipher(EVP_aes_192_cbc()); +    EVP_add_cipher(EVP_aes_192_cfb()); +    EVP_add_cipher(EVP_aes_192_cfb1()); +    EVP_add_cipher(EVP_aes_192_cfb8()); +    EVP_add_cipher(EVP_aes_192_ofb()); +    EVP_add_cipher(EVP_aes_192_ctr()); +    EVP_add_cipher(EVP_aes_192_gcm()); +#ifndef OPENSSL_NO_OCB +    EVP_add_cipher(EVP_aes_192_ocb()); +#endif +    EVP_add_cipher(EVP_aes_192_ccm()); +    EVP_add_cipher(EVP_aes_192_wrap()); +    EVP_add_cipher_alias(SN_id_aes192_wrap, "aes192-wrap"); +    EVP_add_cipher(EVP_aes_192_wrap_pad()); +    EVP_add_cipher_alias(SN_aes_192_cbc, "AES192"); +    EVP_add_cipher_alias(SN_aes_192_cbc, "aes192"); +    EVP_add_cipher(EVP_aes_256_ecb()); +    EVP_add_cipher(EVP_aes_256_cbc()); +    EVP_add_cipher(EVP_aes_256_cfb()); +    EVP_add_cipher(EVP_aes_256_cfb1()); +    EVP_add_cipher(EVP_aes_256_cfb8()); +    EVP_add_cipher(EVP_aes_256_ofb()); +    EVP_add_cipher(EVP_aes_256_ctr()); +    EVP_add_cipher(EVP_aes_256_gcm()); +#ifndef OPENSSL_NO_OCB +    EVP_add_cipher(EVP_aes_256_ocb()); +#endif +    EVP_add_cipher(EVP_aes_256_xts()); +    EVP_add_cipher(EVP_aes_256_ccm()); +    EVP_add_cipher(EVP_aes_256_wrap()); +    EVP_add_cipher_alias(SN_id_aes256_wrap, "aes256-wrap"); +    EVP_add_cipher(EVP_aes_256_wrap_pad()); +    EVP_add_cipher_alias(SN_aes_256_cbc, "AES256"); +    EVP_add_cipher_alias(SN_aes_256_cbc, "aes256"); +    EVP_add_cipher(EVP_aes_128_cbc_hmac_sha1()); +    EVP_add_cipher(EVP_aes_256_cbc_hmac_sha1()); +    EVP_add_cipher(EVP_aes_128_cbc_hmac_sha256()); +    EVP_add_cipher(EVP_aes_256_cbc_hmac_sha256()); + +#ifndef OPENSSL_NO_CAMELLIA +    EVP_add_cipher(EVP_camellia_128_ecb()); +    EVP_add_cipher(EVP_camellia_128_cbc()); +    EVP_add_cipher(EVP_camellia_128_cfb()); +    EVP_add_cipher(EVP_camellia_128_cfb1()); +    EVP_add_cipher(EVP_camellia_128_cfb8()); +    EVP_add_cipher(EVP_camellia_128_ofb()); +    EVP_add_cipher_alias(SN_camellia_128_cbc, "CAMELLIA128"); +    EVP_add_cipher_alias(SN_camellia_128_cbc, "camellia128"); +    EVP_add_cipher(EVP_camellia_192_ecb()); +    EVP_add_cipher(EVP_camellia_192_cbc()); +    EVP_add_cipher(EVP_camellia_192_cfb()); +    EVP_add_cipher(EVP_camellia_192_cfb1()); +    EVP_add_cipher(EVP_camellia_192_cfb8()); +    EVP_add_cipher(EVP_camellia_192_ofb()); +    EVP_add_cipher_alias(SN_camellia_192_cbc, "CAMELLIA192"); +    EVP_add_cipher_alias(SN_camellia_192_cbc, "camellia192"); +    EVP_add_cipher(EVP_camellia_256_ecb()); +    EVP_add_cipher(EVP_camellia_256_cbc()); +    EVP_add_cipher(EVP_camellia_256_cfb()); +    EVP_add_cipher(EVP_camellia_256_cfb1()); +    EVP_add_cipher(EVP_camellia_256_cfb8()); +    EVP_add_cipher(EVP_camellia_256_ofb()); +    EVP_add_cipher_alias(SN_camellia_256_cbc, "CAMELLIA256"); +    EVP_add_cipher_alias(SN_camellia_256_cbc, "camellia256"); +    EVP_add_cipher(EVP_camellia_128_ctr()); +    EVP_add_cipher(EVP_camellia_192_ctr()); +    EVP_add_cipher(EVP_camellia_256_ctr()); +#endif + +#ifndef OPENSSL_NO_CHACHA +    EVP_add_cipher(EVP_chacha20()); +# ifndef OPENSSL_NO_POLY1305 +    EVP_add_cipher(EVP_chacha20_poly1305()); +# endif +#endif +} diff --git a/openssl-1.1.0h/crypto/evp/c_alld.c b/openssl-1.1.0h/crypto/evp/c_alld.c new file mode 100644 index 0000000..ec79734 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/c_alld.c @@ -0,0 +1,49 @@ +/* + * 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 <internal/evp_int.h> +#include <openssl/pkcs12.h> +#include <openssl/objects.h> + +void openssl_add_all_digests_int(void) +{ +#ifndef OPENSSL_NO_MD4 +    EVP_add_digest(EVP_md4()); +#endif +#ifndef OPENSSL_NO_MD5 +    EVP_add_digest(EVP_md5()); +    EVP_add_digest_alias(SN_md5, "ssl3-md5"); +    EVP_add_digest(EVP_md5_sha1()); +#endif +    EVP_add_digest(EVP_sha1()); +    EVP_add_digest_alias(SN_sha1, "ssl3-sha1"); +    EVP_add_digest_alias(SN_sha1WithRSAEncryption, SN_sha1WithRSA); +#if !defined(OPENSSL_NO_MDC2) && !defined(OPENSSL_NO_DES) +    EVP_add_digest(EVP_mdc2()); +#endif +#ifndef OPENSSL_NO_RMD160 +    EVP_add_digest(EVP_ripemd160()); +    EVP_add_digest_alias(SN_ripemd160, "ripemd"); +    EVP_add_digest_alias(SN_ripemd160, "rmd160"); +#endif +    EVP_add_digest(EVP_sha224()); +    EVP_add_digest(EVP_sha256()); +    EVP_add_digest(EVP_sha384()); +    EVP_add_digest(EVP_sha512()); +#ifndef OPENSSL_NO_WHIRLPOOL +    EVP_add_digest(EVP_whirlpool()); +#endif +#ifndef OPENSSL_NO_BLAKE2 +    EVP_add_digest(EVP_blake2b512()); +    EVP_add_digest(EVP_blake2s256()); +#endif +} diff --git a/openssl-1.1.0h/crypto/evp/cmeth_lib.c b/openssl-1.1.0h/crypto/evp/cmeth_lib.c new file mode 100644 index 0000000..e2295c4 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/cmeth_lib.c @@ -0,0 +1,151 @@ +/* + * 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 <string.h> + +#include <openssl/evp.h> +#include "internal/evp_int.h" +#include "evp_locl.h" + +EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len) +{ +    EVP_CIPHER *cipher = OPENSSL_zalloc(sizeof(EVP_CIPHER)); + +    if (cipher != NULL) { +        cipher->nid = cipher_type; +        cipher->block_size = block_size; +        cipher->key_len = key_len; +    } +    return cipher; +} + +EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher) +{ +    EVP_CIPHER *to = EVP_CIPHER_meth_new(cipher->nid, cipher->block_size, +                                         cipher->key_len); + +    if (to != NULL) +        memcpy(to, cipher, sizeof(*to)); +    return to; +} + +void EVP_CIPHER_meth_free(EVP_CIPHER *cipher) +{ +    OPENSSL_free(cipher); +} + +int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len) +{ +    cipher->iv_len = iv_len; +    return 1; +} + +int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags) +{ +    cipher->flags = flags; +    return 1; +} + +int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size) +{ +    cipher->ctx_size = ctx_size; +    return 1; +} + +int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher, +                             int (*init) (EVP_CIPHER_CTX *ctx, +                                          const unsigned char *key, +                                          const unsigned char *iv, +                                          int enc)) +{ +    cipher->init = init; +    return 1; +} + +int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher, +                                  int (*do_cipher) (EVP_CIPHER_CTX *ctx, +                                                    unsigned char *out, +                                                    const unsigned char *in, +                                                    size_t inl)) +{ +    cipher->do_cipher = do_cipher; +    return 1; +} + +int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher, +                                int (*cleanup) (EVP_CIPHER_CTX *)) +{ +    cipher->cleanup = cleanup; +    return 1; +} + +int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher, +                                        int (*set_asn1_parameters) (EVP_CIPHER_CTX *, +                                                                    ASN1_TYPE *)) +{ +    cipher->set_asn1_parameters = set_asn1_parameters; +    return 1; +} + +int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher, +                                        int (*get_asn1_parameters) (EVP_CIPHER_CTX *, +                                                                    ASN1_TYPE *)) +{ +    cipher->get_asn1_parameters = get_asn1_parameters; +    return 1; +} + +int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher, +                             int (*ctrl) (EVP_CIPHER_CTX *, int type, +                                          int arg, void *ptr)) +{ +    cipher->ctrl = ctrl; +    return 1; +} + + +int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, +                                                          const unsigned char *key, +                                                          const unsigned char *iv, +                                                          int enc) +{ +    return cipher->init; +} +int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx, +                                                               unsigned char *out, +                                                               const unsigned char *in, +                                                               size_t inl) +{ +    return cipher->do_cipher; +} + +int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *) +{ +    return cipher->cleanup; +} + +int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, +                                                                     ASN1_TYPE *) +{ +    return cipher->set_asn1_parameters; +} + +int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, +                                                               ASN1_TYPE *) +{ +    return cipher->get_asn1_parameters; +} + +int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, +                                                          int type, int arg, +                                                          void *ptr) +{ +    return cipher->ctrl; +} + diff --git a/openssl-1.1.0h/crypto/evp/digest.c b/openssl-1.1.0h/crypto/evp/digest.c new file mode 100644 index 0000000..65eff7c --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/digest.c @@ -0,0 +1,269 @@ +/* + * 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/evp.h> +#include <openssl/engine.h> +#include "internal/evp_int.h" +#include "evp_locl.h" + +/* This call frees resources associated with the context */ +int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) +{ +    if (ctx == NULL) +        return 1; + +    /* +     * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because +     * sometimes only copies of the context are ever finalised. +     */ +    if (ctx->digest && ctx->digest->cleanup +        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) +        ctx->digest->cleanup(ctx); +    if (ctx->digest && ctx->digest->ctx_size && ctx->md_data +        && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { +        OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); +    } +    EVP_PKEY_CTX_free(ctx->pctx); +#ifndef OPENSSL_NO_ENGINE +    ENGINE_finish(ctx->engine); +#endif +    OPENSSL_cleanse(ctx, sizeof(*ctx)); + +    return 1; +} + +EVP_MD_CTX *EVP_MD_CTX_new(void) +{ +    return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); +} + +void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ +    EVP_MD_CTX_reset(ctx); +    OPENSSL_free(ctx); +} + +int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) +{ +    EVP_MD_CTX_reset(ctx); +    return EVP_DigestInit_ex(ctx, type, NULL); +} + +int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) +{ +    EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); +#ifndef OPENSSL_NO_ENGINE +    /* +     * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so +     * this context may already have an ENGINE! Try to avoid releasing the +     * previous handle, re-querying for an ENGINE, and having a +     * reinitialisation, when it may all be unnecessary. +     */ +    if (ctx->engine && ctx->digest && +        (type == NULL || (type->type == ctx->digest->type))) +        goto skip_to_init; +    if (type) { +        /* +         * Ensure an ENGINE left lying around from last time is cleared (the +         * previous check attempted to avoid this if the same ENGINE and +         * EVP_MD could be used). +         */ +        ENGINE_finish(ctx->engine); +        if (impl != NULL) { +            if (!ENGINE_init(impl)) { +                EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); +                return 0; +            } +        } else { +            /* Ask if an ENGINE is reserved for this job */ +            impl = ENGINE_get_digest_engine(type->type); +        } +        if (impl != NULL) { +            /* There's an ENGINE for this job ... (apparently) */ +            const EVP_MD *d = ENGINE_get_digest(impl, type->type); + +            if (d == NULL) { +                EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); +                ENGINE_finish(impl); +                return 0; +            } +            /* We'll use the ENGINE's private digest definition */ +            type = d; +            /* +             * Store the ENGINE functional reference so we know 'type' came +             * from an ENGINE and we need to release it when done. +             */ +            ctx->engine = impl; +        } else +            ctx->engine = NULL; +    } else { +        if (!ctx->digest) { +            EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_NO_DIGEST_SET); +            return 0; +        } +        type = ctx->digest; +    } +#endif +    if (ctx->digest != type) { +        if (ctx->digest && ctx->digest->ctx_size) { +            OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); +            ctx->md_data = NULL; +        } +        ctx->digest = type; +        if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) { +            ctx->update = type->update; +            ctx->md_data = OPENSSL_zalloc(type->ctx_size); +            if (ctx->md_data == NULL) { +                EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE); +                return 0; +            } +        } +    } +#ifndef OPENSSL_NO_ENGINE + skip_to_init: +#endif +    if (ctx->pctx) { +        int r; +        r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG, +                              EVP_PKEY_CTRL_DIGESTINIT, 0, ctx); +        if (r <= 0 && (r != -2)) +            return 0; +    } +    if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) +        return 1; +    return ctx->digest->init(ctx); +} + +int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return ctx->update(ctx, data, count); +} + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) +{ +    int ret; +    ret = EVP_DigestFinal_ex(ctx, md, size); +    EVP_MD_CTX_reset(ctx); +    return ret; +} + +/* The caller can assume that this removes any secret data from the context */ +int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size) +{ +    int ret; + +    OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE); +    ret = ctx->digest->final(ctx, md); +    if (size != NULL) +        *size = ctx->digest->md_size; +    if (ctx->digest->cleanup) { +        ctx->digest->cleanup(ctx); +        EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); +    } +    OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size); +    return ret; +} + +int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in) +{ +    EVP_MD_CTX_reset(out); +    return EVP_MD_CTX_copy_ex(out, in); +} + +int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) +{ +    unsigned char *tmp_buf; +    if ((in == NULL) || (in->digest == NULL)) { +        EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED); +        return 0; +    } +#ifndef OPENSSL_NO_ENGINE +    /* Make sure it's safe to copy a digest context using an ENGINE */ +    if (in->engine && !ENGINE_init(in->engine)) { +        EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB); +        return 0; +    } +#endif + +    if (out->digest == in->digest) { +        tmp_buf = out->md_data; +        EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE); +    } else +        tmp_buf = NULL; +    EVP_MD_CTX_reset(out); +    memcpy(out, in, sizeof(*out)); + +    /* Null these variables, since they are getting fixed up +     * properly below.  Anything else may cause a memleak and/or +     * double free if any of the memory allocations below fail +     */ +    out->md_data = NULL; +    out->pctx = NULL; + +    if (in->md_data && out->digest->ctx_size) { +        if (tmp_buf) +            out->md_data = tmp_buf; +        else { +            out->md_data = OPENSSL_malloc(out->digest->ctx_size); +            if (out->md_data == NULL) { +                EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_MALLOC_FAILURE); +                return 0; +            } +        } +        memcpy(out->md_data, in->md_data, out->digest->ctx_size); +    } + +    out->update = in->update; + +    if (in->pctx) { +        out->pctx = EVP_PKEY_CTX_dup(in->pctx); +        if (!out->pctx) { +            EVP_MD_CTX_reset(out); +            return 0; +        } +    } + +    if (out->digest->copy) +        return out->digest->copy(out, in); + +    return 1; +} + +int EVP_Digest(const void *data, size_t count, +               unsigned char *md, unsigned int *size, const EVP_MD *type, +               ENGINE *impl) +{ +    EVP_MD_CTX *ctx = EVP_MD_CTX_new(); +    int ret; + +    if (ctx == NULL) +        return 0; +    EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT); +    ret = EVP_DigestInit_ex(ctx, type, impl) +        && EVP_DigestUpdate(ctx, data, count) +        && EVP_DigestFinal_ex(ctx, md, size); +    EVP_MD_CTX_free(ctx); + +    return ret; +} + +int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2) +{ +    if (ctx->digest && ctx->digest->md_ctrl) { +        int ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2); +        if (ret <= 0) +            return 0; +        return 1; +    } +    return 0; +} diff --git a/openssl-1.1.0h/crypto/evp/e_aes.c b/openssl-1.1.0h/crypto/evp/e_aes.c new file mode 100644 index 0000000..3f36d70 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_aes.c @@ -0,0 +1,2705 @@ +/* + * Copyright 2001-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 <openssl/opensslconf.h> +#include <openssl/crypto.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <string.h> +#include <assert.h> +#include <openssl/aes.h> +#include "internal/evp_int.h" +#include "modes_lcl.h" +#include <openssl/rand.h> +#include "evp_locl.h" + +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ks; +    block128_f block; +    union { +        cbc128_f cbc; +        ctr128_f ctr; +    } stream; +} EVP_AES_KEY; + +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ks;                       /* AES key schedule to use */ +    int key_set;                /* Set if key initialised */ +    int iv_set;                 /* Set if an iv is set */ +    GCM128_CONTEXT gcm; +    unsigned char *iv;          /* Temporary IV store */ +    int ivlen;                  /* IV length */ +    int taglen; +    int iv_gen;                 /* It is OK to generate IVs */ +    int tls_aad_len;            /* TLS AAD length */ +    ctr128_f ctr; +} EVP_AES_GCM_CTX; + +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ks1, ks2;                 /* AES key schedules to use */ +    XTS128_CONTEXT xts; +    void (*stream) (const unsigned char *in, +                    unsigned char *out, size_t length, +                    const AES_KEY *key1, const AES_KEY *key2, +                    const unsigned char iv[16]); +} EVP_AES_XTS_CTX; + +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ks;                       /* AES key schedule to use */ +    int key_set;                /* Set if key initialised */ +    int iv_set;                 /* Set if an iv is set */ +    int tag_set;                /* Set if tag is valid */ +    int len_set;                /* Set if message length set */ +    int L, M;                   /* L and M parameters from RFC3610 */ +    int tls_aad_len;            /* TLS AAD length */ +    CCM128_CONTEXT ccm; +    ccm128_f str; +} EVP_AES_CCM_CTX; + +#ifndef OPENSSL_NO_OCB +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ksenc;                    /* AES key schedule to use for encryption */ +    union { +        double align; +        AES_KEY ks; +    } ksdec;                    /* AES key schedule to use for decryption */ +    int key_set;                /* Set if key initialised */ +    int iv_set;                 /* Set if an iv is set */ +    OCB128_CONTEXT ocb; +    unsigned char *iv;          /* Temporary IV store */ +    unsigned char tag[16]; +    unsigned char data_buf[16]; /* Store partial data blocks */ +    unsigned char aad_buf[16];  /* Store partial AAD blocks */ +    int data_buf_len; +    int aad_buf_len; +    int ivlen;                  /* IV length */ +    int taglen; +} EVP_AES_OCB_CTX; +#endif + +#define MAXBITCHUNK     ((size_t)1<<(sizeof(size_t)*8-4)) + +#ifdef VPAES_ASM +int vpaes_set_encrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); +int vpaes_set_decrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); + +void vpaes_encrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); +void vpaes_decrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); + +void vpaes_cbc_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key, unsigned char *ivec, int enc); +#endif +#ifdef BSAES_ASM +void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out, +                       size_t length, const AES_KEY *key, +                       unsigned char ivec[16], int enc); +void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out, +                                size_t len, const AES_KEY *key, +                                const unsigned char ivec[16]); +void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out, +                       size_t len, const AES_KEY *key1, +                       const AES_KEY *key2, const unsigned char iv[16]); +void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out, +                       size_t len, const AES_KEY *key1, +                       const AES_KEY *key2, const unsigned char iv[16]); +#endif +#ifdef AES_CTR_ASM +void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                       size_t blocks, const AES_KEY *key, +                       const unsigned char ivec[AES_BLOCK_SIZE]); +#endif +#ifdef AES_XTS_ASM +void AES_xts_encrypt(const char *inp, char *out, size_t len, +                     const AES_KEY *key1, const AES_KEY *key2, +                     const unsigned char iv[16]); +void AES_xts_decrypt(const char *inp, char *out, size_t len, +                     const AES_KEY *key1, const AES_KEY *key2, +                     const unsigned char iv[16]); +#endif + +#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)) +# include "ppc_arch.h" +# ifdef VPAES_ASM +#  define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC) +# endif +# define HWAES_CAPABLE  (OPENSSL_ppccap_P & PPC_CRYPTO207) +# define HWAES_set_encrypt_key aes_p8_set_encrypt_key +# define HWAES_set_decrypt_key aes_p8_set_decrypt_key +# define HWAES_encrypt aes_p8_encrypt +# define HWAES_decrypt aes_p8_decrypt +# define HWAES_cbc_encrypt aes_p8_cbc_encrypt +# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks +# define HWAES_xts_encrypt aes_p8_xts_encrypt +# define HWAES_xts_decrypt aes_p8_xts_decrypt +#endif + +#if     defined(AES_ASM) && !defined(I386_ONLY) &&      (  \ +        ((defined(__i386)       || defined(__i386__)    || \ +          defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \ +        defined(__x86_64)       || defined(__x86_64__)  || \ +        defined(_M_AMD64)       || defined(_M_X64)      ) + +extern unsigned int OPENSSL_ia32cap_P[]; + +# ifdef VPAES_ASM +#  define VPAES_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(41-32))) +# endif +# ifdef BSAES_ASM +#  define BSAES_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(41-32))) +# endif +/* + * AES-NI section + */ +# define AESNI_CAPABLE   (OPENSSL_ia32cap_P[1]&(1<<(57-32))) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); + +void aesni_encrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); +void aesni_decrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); + +void aesni_ecb_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, const AES_KEY *key, int enc); +void aesni_cbc_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key, unsigned char *ivec, int enc); + +void aesni_ctr32_encrypt_blocks(const unsigned char *in, +                                unsigned char *out, +                                size_t blocks, +                                const void *key, const unsigned char *ivec); + +void aesni_xts_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key1, const AES_KEY *key2, +                       const unsigned char iv[16]); + +void aesni_xts_decrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key1, const AES_KEY *key2, +                       const unsigned char iv[16]); + +void aesni_ccm64_encrypt_blocks(const unsigned char *in, +                                unsigned char *out, +                                size_t blocks, +                                const void *key, +                                const unsigned char ivec[16], +                                unsigned char cmac[16]); + +void aesni_ccm64_decrypt_blocks(const unsigned char *in, +                                unsigned char *out, +                                size_t blocks, +                                const void *key, +                                const unsigned char ivec[16], +                                unsigned char cmac[16]); + +# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64) +size_t aesni_gcm_encrypt(const unsigned char *in, +                         unsigned char *out, +                         size_t len, +                         const void *key, unsigned char ivec[16], u64 *Xi); +#  define AES_gcm_encrypt aesni_gcm_encrypt +size_t aesni_gcm_decrypt(const unsigned char *in, +                         unsigned char *out, +                         size_t len, +                         const void *key, unsigned char ivec[16], u64 *Xi); +#  define AES_gcm_decrypt aesni_gcm_decrypt +void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in, +                   size_t len); +#  define AES_GCM_ASM(gctx)       (gctx->ctr==aesni_ctr32_encrypt_blocks && \ +                                 gctx->gcm.ghash==gcm_ghash_avx) +#  define AES_GCM_ASM2(gctx)      (gctx->gcm.block==(block128_f)aesni_encrypt && \ +                                 gctx->gcm.ghash==gcm_ghash_avx) +#  undef AES_GCM_ASM2          /* minor size optimization */ +# endif + +static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                          const unsigned char *iv, int enc) +{ +    int ret, mode; +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    mode = EVP_CIPHER_CTX_mode(ctx); +    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) +        && !enc) { +        ret = aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &dat->ks.ks); +        dat->block = (block128_f) aesni_decrypt; +        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +            (cbc128_f) aesni_cbc_encrypt : NULL; +    } else { +        ret = aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &dat->ks.ks); +        dat->block = (block128_f) aesni_encrypt; +        if (mode == EVP_CIPH_CBC_MODE) +            dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; +        else if (mode == EVP_CIPH_CTR_MODE) +            dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; +        else +            dat->stream.cbc = NULL; +    } + +    if (ret < 0) { +        EVPerr(EVP_F_AESNI_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); +        return 0; +    } + +    return 1; +} + +static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len) +{ +    aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks, +                      EVP_CIPHER_CTX_iv_noconst(ctx), +                      EVP_CIPHER_CTX_encrypting(ctx)); + +    return 1; +} + +static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len) +{ +    size_t bl = EVP_CIPHER_CTX_block_size(ctx); + +    if (len < bl) +        return 1; + +    aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks, +                      EVP_CIPHER_CTX_encrypting(ctx)); + +    return 1; +} + +# define aesni_ofb_cipher aes_ofb_cipher +static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +# define aesni_cfb_cipher aes_cfb_cipher +static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +# define aesni_cfb8_cipher aes_cfb8_cipher +static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aesni_cfb1_cipher aes_cfb1_cipher +static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aesni_ctr_cipher aes_ctr_cipher +static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                              const unsigned char *iv, int enc) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                              &gctx->ks.ks); +        CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt); +        gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; +        /* +         * If we have an iv can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && gctx->iv_set) +            iv = gctx->iv; +        if (iv) { +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +            gctx->iv_set = 1; +        } +        gctx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (gctx->key_set) +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +        else +            memcpy(gctx->iv, iv, gctx->ivlen); +        gctx->iv_set = 1; +        gctx->iv_gen = 0; +    } +    return 1; +} + +# define aesni_gcm_cipher aes_gcm_cipher +static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                              const unsigned char *iv, int enc) +{ +    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); +    if (!iv && !key) +        return 1; + +    if (key) { +        /* key_len is two AES keys */ +        if (enc) { +            aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, +                                  &xctx->ks1.ks); +            xctx->xts.block1 = (block128_f) aesni_encrypt; +            xctx->stream = aesni_xts_encrypt; +        } else { +            aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, +                                  &xctx->ks1.ks); +            xctx->xts.block1 = (block128_f) aesni_decrypt; +            xctx->stream = aesni_xts_decrypt; +        } + +        aesni_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, +                              EVP_CIPHER_CTX_key_length(ctx) * 4, +                              &xctx->ks2.ks); +        xctx->xts.block2 = (block128_f) aesni_encrypt; + +        xctx->xts.key1 = &xctx->ks1; +    } + +    if (iv) { +        xctx->xts.key2 = &xctx->ks2; +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); +    } + +    return 1; +} + +# define aesni_xts_cipher aes_xts_cipher +static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                              const unsigned char *iv, int enc) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                              &cctx->ks.ks); +        CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, +                           &cctx->ks, (block128_f) aesni_encrypt); +        cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks : +            (ccm128_f) aesni_ccm64_decrypt_blocks; +        cctx->key_set = 1; +    } +    if (iv) { +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); +        cctx->iv_set = 1; +    } +    return 1; +} + +# define aesni_ccm_cipher aes_ccm_cipher +static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); + +# ifndef OPENSSL_NO_OCB +void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out, +                       size_t blocks, const void *key, +                       size_t start_block_num, +                       unsigned char offset_i[16], +                       const unsigned char L_[][16], +                       unsigned char checksum[16]); +void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out, +                       size_t blocks, const void *key, +                       size_t start_block_num, +                       unsigned char offset_i[16], +                       const unsigned char L_[][16], +                       unsigned char checksum[16]); + +static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                              const unsigned char *iv, int enc) +{ +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        do { +            /* +             * We set both the encrypt and decrypt key here because decrypt +             * needs both. We could possibly optimise to remove setting the +             * decrypt for an encryption operation. +             */ +            aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                  &octx->ksenc.ks); +            aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                  &octx->ksdec.ks); +            if (!CRYPTO_ocb128_init(&octx->ocb, +                                    &octx->ksenc.ks, &octx->ksdec.ks, +                                    (block128_f) aesni_encrypt, +                                    (block128_f) aesni_decrypt, +                                    enc ? aesni_ocb_encrypt +                                        : aesni_ocb_decrypt)) +                return 0; +        } +        while (0); + +        /* +         * If we have an iv we can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && octx->iv_set) +            iv = octx->iv; +        if (iv) { +            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) +                != 1) +                return 0; +            octx->iv_set = 1; +        } +        octx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (octx->key_set) +            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); +        else +            memcpy(octx->iv, iv, octx->ivlen); +        octx->iv_set = 1; +    } +    return 1; +} + +#  define aesni_ocb_cipher aes_ocb_cipher +static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t len); +# endif                        /* OPENSSL_NO_OCB */ + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aesni_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aesni_init_key,                 \ +        aesni_##mode##_cipher,          \ +        NULL,                           \ +        sizeof(EVP_AES_KEY),            \ +        NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,     \ +        keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_init_key,                   \ +        aes_##mode##_cipher,            \ +        NULL,                           \ +        sizeof(EVP_AES_KEY),            \ +        NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aesni_##keylen##_##mode = { \ +        nid##_##keylen##_##mode,blocksize, \ +        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aesni_##mode##_init_key,        \ +        aesni_##mode##_cipher,          \ +        aes_##mode##_cleanup,           \ +        sizeof(EVP_AES_##MODE##_CTX),   \ +        NULL,NULL,aes_##mode##_ctrl,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##mode,blocksize, \ +        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_##mode##_init_key,          \ +        aes_##mode##_cipher,            \ +        aes_##mode##_cleanup,           \ +        sizeof(EVP_AES_##MODE##_CTX),   \ +        NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; } + +#elif   defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) + +# include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +/* + * Initial Fujitsu SPARC64 X support + */ +# define HWAES_CAPABLE           (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX) +# define HWAES_set_encrypt_key aes_fx_set_encrypt_key +# define HWAES_set_decrypt_key aes_fx_set_decrypt_key +# define HWAES_encrypt aes_fx_encrypt +# define HWAES_decrypt aes_fx_decrypt +# define HWAES_cbc_encrypt aes_fx_cbc_encrypt +# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks + +# define SPARC_AES_CAPABLE       (OPENSSL_sparcv9cap_P[1] & CFR_AES) + +void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks); +void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks); +void aes_t4_encrypt(const unsigned char *in, unsigned char *out, +                    const AES_KEY *key); +void aes_t4_decrypt(const unsigned char *in, unsigned char *out, +                    const AES_KEY *key); +/* + * Key-length specific subroutines were chosen for following reason. + * Each SPARC T4 core can execute up to 8 threads which share core's + * resources. Loading as much key material to registers allows to + * minimize references to shared memory interface, as well as amount + * of instructions in inner loops [much needed on T4]. But then having + * non-key-length specific routines would require conditional branches + * either in inner loops or on subroutines' entries. Former is hardly + * acceptable, while latter means code size increase to size occupied + * by multiple key-length specific subroutines, so why fight? + */ +void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, +                           size_t len, const AES_KEY *key, +                           unsigned char *ivec); +void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                             size_t blocks, const AES_KEY *key, +                             unsigned char *ivec); +void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                             size_t blocks, const AES_KEY *key, +                             unsigned char *ivec); +void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                             size_t blocks, const AES_KEY *key, +                             unsigned char *ivec); +void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out, +                           size_t blocks, const AES_KEY *key1, +                           const AES_KEY *key2, const unsigned char *ivec); +void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out, +                           size_t blocks, const AES_KEY *key1, +                           const AES_KEY *key2, const unsigned char *ivec); +void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out, +                           size_t blocks, const AES_KEY *key1, +                           const AES_KEY *key2, const unsigned char *ivec); +void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out, +                           size_t blocks, const AES_KEY *key1, +                           const AES_KEY *key2, const unsigned char *ivec); + +static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                           const unsigned char *iv, int enc) +{ +    int ret, mode, bits; +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    mode = EVP_CIPHER_CTX_mode(ctx); +    bits = EVP_CIPHER_CTX_key_length(ctx) * 8; +    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) +        && !enc) { +        ret = 0; +        aes_t4_set_decrypt_key(key, bits, &dat->ks.ks); +        dat->block = (block128_f) aes_t4_decrypt; +        switch (bits) { +        case 128: +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) aes128_t4_cbc_decrypt : NULL; +            break; +        case 192: +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) aes192_t4_cbc_decrypt : NULL; +            break; +        case 256: +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) aes256_t4_cbc_decrypt : NULL; +            break; +        default: +            ret = -1; +        } +    } else { +        ret = 0; +        aes_t4_set_encrypt_key(key, bits, &dat->ks.ks); +        dat->block = (block128_f) aes_t4_encrypt; +        switch (bits) { +        case 128: +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt; +            else if (mode == EVP_CIPH_CTR_MODE) +                dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt; +            else +                dat->stream.cbc = NULL; +            break; +        case 192: +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt; +            else if (mode == EVP_CIPH_CTR_MODE) +                dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt; +            else +                dat->stream.cbc = NULL; +            break; +        case 256: +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt; +            else if (mode == EVP_CIPH_CTR_MODE) +                dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt; +            else +                dat->stream.cbc = NULL; +            break; +        default: +            ret = -1; +        } +    } + +    if (ret < 0) { +        EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); +        return 0; +    } + +    return 1; +} + +# define aes_t4_cbc_cipher aes_cbc_cipher +static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aes_t4_ecb_cipher aes_ecb_cipher +static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aes_t4_ofb_cipher aes_ofb_cipher +static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aes_t4_cfb_cipher aes_cfb_cipher +static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# define aes_t4_cfb8_cipher aes_cfb8_cipher +static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +# define aes_t4_cfb1_cipher aes_cfb1_cipher +static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +# define aes_t4_ctr_cipher aes_ctr_cipher +static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        int bits = EVP_CIPHER_CTX_key_length(ctx) * 8; +        aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks); +        CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, +                           (block128_f) aes_t4_encrypt); +        switch (bits) { +        case 128: +            gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt; +            break; +        case 192: +            gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt; +            break; +        case 256: +            gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt; +            break; +        default: +            return 0; +        } +        /* +         * If we have an iv can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && gctx->iv_set) +            iv = gctx->iv; +        if (iv) { +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +            gctx->iv_set = 1; +        } +        gctx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (gctx->key_set) +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +        else +            memcpy(gctx->iv, iv, gctx->ivlen); +        gctx->iv_set = 1; +        gctx->iv_gen = 0; +    } +    return 1; +} + +# define aes_t4_gcm_cipher aes_gcm_cipher +static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc) +{ +    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); +    if (!iv && !key) +        return 1; + +    if (key) { +        int bits = EVP_CIPHER_CTX_key_length(ctx) * 4; +        xctx->stream = NULL; +        /* key_len is two AES keys */ +        if (enc) { +            aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks); +            xctx->xts.block1 = (block128_f) aes_t4_encrypt; +            switch (bits) { +            case 128: +                xctx->stream = aes128_t4_xts_encrypt; +                break; +            case 256: +                xctx->stream = aes256_t4_xts_encrypt; +                break; +            default: +                return 0; +            } +        } else { +            aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, +                                   &xctx->ks1.ks); +            xctx->xts.block1 = (block128_f) aes_t4_decrypt; +            switch (bits) { +            case 128: +                xctx->stream = aes128_t4_xts_decrypt; +                break; +            case 256: +                xctx->stream = aes256_t4_xts_decrypt; +                break; +            default: +                return 0; +            } +        } + +        aes_t4_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, +                               EVP_CIPHER_CTX_key_length(ctx) * 4, +                               &xctx->ks2.ks); +        xctx->xts.block2 = (block128_f) aes_t4_encrypt; + +        xctx->xts.key1 = &xctx->ks1; +    } + +    if (iv) { +        xctx->xts.key2 = &xctx->ks2; +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); +    } + +    return 1; +} + +# define aes_t4_xts_cipher aes_xts_cipher +static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        int bits = EVP_CIPHER_CTX_key_length(ctx) * 8; +        aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks); +        CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, +                           &cctx->ks, (block128_f) aes_t4_encrypt); +        cctx->str = NULL; +        cctx->key_set = 1; +    } +    if (iv) { +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); +        cctx->iv_set = 1; +    } +    return 1; +} + +# define aes_t4_ccm_cipher aes_ccm_cipher +static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); + +# ifndef OPENSSL_NO_OCB +static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc) +{ +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        do { +            /* +             * We set both the encrypt and decrypt key here because decrypt +             * needs both. We could possibly optimise to remove setting the +             * decrypt for an encryption operation. +             */ +            aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                   &octx->ksenc.ks); +            aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                   &octx->ksdec.ks); +            if (!CRYPTO_ocb128_init(&octx->ocb, +                                    &octx->ksenc.ks, &octx->ksdec.ks, +                                    (block128_f) aes_t4_encrypt, +                                    (block128_f) aes_t4_decrypt, +                                    NULL)) +                return 0; +        } +        while (0); + +        /* +         * If we have an iv we can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && octx->iv_set) +            iv = octx->iv; +        if (iv) { +            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) +                != 1) +                return 0; +            octx->iv_set = 1; +        } +        octx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (octx->key_set) +            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); +        else +            memcpy(octx->iv, iv, octx->ivlen); +        octx->iv_set = 1; +    } +    return 1; +} + +#  define aes_t4_ocb_cipher aes_ocb_cipher +static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                             const unsigned char *in, size_t len); +# endif                        /* OPENSSL_NO_OCB */ + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aes_t4_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_t4_init_key,                \ +        aes_t4_##mode##_cipher,         \ +        NULL,                           \ +        sizeof(EVP_AES_KEY),            \ +        NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,     \ +        keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_init_key,                   \ +        aes_##mode##_cipher,            \ +        NULL,                           \ +        sizeof(EVP_AES_KEY),            \ +        NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aes_t4_##keylen##_##mode = { \ +        nid##_##keylen##_##mode,blocksize, \ +        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_t4_##mode##_init_key,       \ +        aes_t4_##mode##_cipher,         \ +        aes_##mode##_cleanup,           \ +        sizeof(EVP_AES_##MODE##_CTX),   \ +        NULL,NULL,aes_##mode##_ctrl,NULL }; \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##mode,blocksize, \ +        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_##mode##_init_key,          \ +        aes_##mode##_cipher,            \ +        aes_##mode##_cleanup,           \ +        sizeof(EVP_AES_##MODE##_CTX),   \ +        NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; } + +#else + +# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_init_key,                   \ +        aes_##mode##_cipher,            \ +        NULL,                           \ +        sizeof(EVP_AES_KEY),            \ +        NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return &aes_##keylen##_##mode; } + +# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \ +static const EVP_CIPHER aes_##keylen##_##mode = { \ +        nid##_##keylen##_##mode,blocksize, \ +        (EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        aes_##mode##_init_key,          \ +        aes_##mode##_cipher,            \ +        aes_##mode##_cleanup,           \ +        sizeof(EVP_AES_##MODE##_CTX),   \ +        NULL,NULL,aes_##mode##_ctrl,NULL }; \ +const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \ +{ return &aes_##keylen##_##mode; } + +#endif + +#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__)) +# include "arm_arch.h" +# if __ARM_MAX_ARCH__>=7 +#  if defined(BSAES_ASM) +#   define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) +#  endif +#  if defined(VPAES_ASM) +#   define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON) +#  endif +#  define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES) +#  define HWAES_set_encrypt_key aes_v8_set_encrypt_key +#  define HWAES_set_decrypt_key aes_v8_set_decrypt_key +#  define HWAES_encrypt aes_v8_encrypt +#  define HWAES_decrypt aes_v8_decrypt +#  define HWAES_cbc_encrypt aes_v8_cbc_encrypt +#  define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks +# endif +#endif + +#if defined(HWAES_CAPABLE) +int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits, +                          AES_KEY *key); +int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits, +                          AES_KEY *key); +void HWAES_encrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); +void HWAES_decrypt(const unsigned char *in, unsigned char *out, +                   const AES_KEY *key); +void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out, +                       size_t length, const AES_KEY *key, +                       unsigned char *ivec, const int enc); +void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out, +                                size_t len, const AES_KEY *key, +                                const unsigned char ivec[16]); +void HWAES_xts_encrypt(const unsigned char *inp, unsigned char *out, +                       size_t len, const AES_KEY *key1, +                       const AES_KEY *key2, const unsigned char iv[16]); +void HWAES_xts_decrypt(const unsigned char *inp, unsigned char *out, +                       size_t len, const AES_KEY *key1, +                       const AES_KEY *key2, const unsigned char iv[16]); +#endif + +#define BLOCK_CIPHER_generic_pack(nid,keylen,flags)             \ +        BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)     \ +        BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)      \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags)       \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)       \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags) + +static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc) +{ +    int ret, mode; +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    mode = EVP_CIPHER_CTX_mode(ctx); +    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) +        && !enc) { +#ifdef HWAES_CAPABLE +        if (HWAES_CAPABLE) { +            ret = HWAES_set_decrypt_key(key, +                                        EVP_CIPHER_CTX_key_length(ctx) * 8, +                                        &dat->ks.ks); +            dat->block = (block128_f) HWAES_decrypt; +            dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt; +# endif +        } else +#endif +#ifdef BSAES_CAPABLE +        if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) { +            ret = AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &dat->ks.ks); +            dat->block = (block128_f) AES_decrypt; +            dat->stream.cbc = (cbc128_f) bsaes_cbc_encrypt; +        } else +#endif +#ifdef VPAES_CAPABLE +        if (VPAES_CAPABLE) { +            ret = vpaes_set_decrypt_key(key, +                                        EVP_CIPHER_CTX_key_length(ctx) * 8, +                                        &dat->ks.ks); +            dat->block = (block128_f) vpaes_decrypt; +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) vpaes_cbc_encrypt : NULL; +        } else +#endif +        { +            ret = AES_set_decrypt_key(key, +                                      EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &dat->ks.ks); +            dat->block = (block128_f) AES_decrypt; +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) AES_cbc_encrypt : NULL; +        } +    } else +#ifdef HWAES_CAPABLE +    if (HWAES_CAPABLE) { +        ret = HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &dat->ks.ks); +        dat->block = (block128_f) HWAES_encrypt; +        dat->stream.cbc = NULL; +# ifdef HWAES_cbc_encrypt +        if (mode == EVP_CIPH_CBC_MODE) +            dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt; +        else +# endif +# ifdef HWAES_ctr32_encrypt_blocks +        if (mode == EVP_CIPH_CTR_MODE) +            dat->stream.ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks; +        else +# endif +            (void)0;            /* terminate potentially open 'else' */ +    } else +#endif +#ifdef BSAES_CAPABLE +    if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) { +        ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                  &dat->ks.ks); +        dat->block = (block128_f) AES_encrypt; +        dat->stream.ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks; +    } else +#endif +#ifdef VPAES_CAPABLE +    if (VPAES_CAPABLE) { +        ret = vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &dat->ks.ks); +        dat->block = (block128_f) vpaes_encrypt; +        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +            (cbc128_f) vpaes_cbc_encrypt : NULL; +    } else +#endif +    { +        ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                  &dat->ks.ks); +        dat->block = (block128_f) AES_encrypt; +        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +            (cbc128_f) AES_cbc_encrypt : NULL; +#ifdef AES_CTR_ASM +        if (mode == EVP_CIPH_CTR_MODE) +            dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt; +#endif +    } + +    if (ret < 0) { +        EVPerr(EVP_F_AES_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED); +        return 0; +    } + +    return 1; +} + +static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    if (dat->stream.cbc) +        (*dat->stream.cbc) (in, out, len, &dat->ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx), +                            EVP_CIPHER_CTX_encrypting(ctx)); +    else if (EVP_CIPHER_CTX_encrypting(ctx)) +        CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); +    else +        CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + +    return 1; +} + +static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    size_t bl = EVP_CIPHER_CTX_block_size(ctx); +    size_t i; +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    if (len < bl) +        return 1; + +    for (i = 0, len -= bl; i <= len; i += bl) +        (*dat->block) (in + i, out + i, &dat->ks); + +    return 1; +} + +static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, +                          EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, +                          EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                          EVP_CIPHER_CTX_encrypting(ctx), dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t len) +{ +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                            EVP_CIPHER_CTX_encrypting(ctx), dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t len) +{ +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                                EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +        return 1; +    } + +    while (len >= MAXBITCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                                EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +        len -= MAXBITCHUNK; +        out += MAXBITCHUNK; +        in  += MAXBITCHUNK; +    } +    if (len) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                                EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } + +    return 1; +} + +static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    unsigned int num = EVP_CIPHER_CTX_num(ctx); +    EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + +    if (dat->stream.ctr) +        CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, +                                    EVP_CIPHER_CTX_iv_noconst(ctx), +                                    EVP_CIPHER_CTX_buf_noconst(ctx), +                                    &num, dat->stream.ctr); +    else +        CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), +                              EVP_CIPHER_CTX_buf_noconst(ctx), &num, +                              dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +BLOCK_CIPHER_generic_pack(NID_aes, 128, 0) +    BLOCK_CIPHER_generic_pack(NID_aes, 192, 0) +    BLOCK_CIPHER_generic_pack(NID_aes, 256, 0) + +static int aes_gcm_cleanup(EVP_CIPHER_CTX *c) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c); +    if (gctx == NULL) +        return 0; +    OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm)); +    if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) +        OPENSSL_free(gctx->iv); +    return 1; +} + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ +    int n = 8; +    unsigned char c; + +    do { +        --n; +        c = counter[n]; +        ++c; +        counter[n] = c; +        if (c) +            return; +    } while (n); +} + +static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c); +    switch (type) { +    case EVP_CTRL_INIT: +        gctx->key_set = 0; +        gctx->iv_set = 0; +        gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); +        gctx->iv = EVP_CIPHER_CTX_iv_noconst(c); +        gctx->taglen = -1; +        gctx->iv_gen = 0; +        gctx->tls_aad_len = -1; +        return 1; + +    case EVP_CTRL_AEAD_SET_IVLEN: +        if (arg <= 0) +            return 0; +        /* Allocate memory for IV if needed */ +        if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { +            if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) +                OPENSSL_free(gctx->iv); +            gctx->iv = OPENSSL_malloc(arg); +            if (gctx->iv == NULL) +                return 0; +        } +        gctx->ivlen = arg; +        return 1; + +    case EVP_CTRL_AEAD_SET_TAG: +        if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c)) +            return 0; +        memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); +        gctx->taglen = arg; +        return 1; + +    case EVP_CTRL_AEAD_GET_TAG: +        if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c) +            || gctx->taglen < 0) +            return 0; +        memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg); +        return 1; + +    case EVP_CTRL_GCM_SET_IV_FIXED: +        /* Special case: -1 length restores whole IV */ +        if (arg == -1) { +            memcpy(gctx->iv, ptr, gctx->ivlen); +            gctx->iv_gen = 1; +            return 1; +        } +        /* +         * Fixed field must be at least 4 bytes and invocation field at least +         * 8. +         */ +        if ((arg < 4) || (gctx->ivlen - arg) < 8) +            return 0; +        if (arg) +            memcpy(gctx->iv, ptr, arg); +        if (EVP_CIPHER_CTX_encrypting(c) +            && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) +            return 0; +        gctx->iv_gen = 1; +        return 1; + +    case EVP_CTRL_GCM_IV_GEN: +        if (gctx->iv_gen == 0 || gctx->key_set == 0) +            return 0; +        CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); +        if (arg <= 0 || arg > gctx->ivlen) +            arg = gctx->ivlen; +        memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); +        /* +         * Invocation field will be at least 8 bytes in size and so no need +         * to check wrap around or increment more than last 8 bytes. +         */ +        ctr64_inc(gctx->iv + gctx->ivlen - 8); +        gctx->iv_set = 1; +        return 1; + +    case EVP_CTRL_GCM_SET_IV_INV: +        if (gctx->iv_gen == 0 || gctx->key_set == 0 +            || EVP_CIPHER_CTX_encrypting(c)) +            return 0; +        memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); +        CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); +        gctx->iv_set = 1; +        return 1; + +    case EVP_CTRL_AEAD_TLS1_AAD: +        /* Save the AAD for later use */ +        if (arg != EVP_AEAD_TLS1_AAD_LEN) +            return 0; +        memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); +        gctx->tls_aad_len = arg; +        { +            unsigned int len = +                EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 +                | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; +            /* Correct length for explicit IV */ +            if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN) +                return 0; +            len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; +            /* If decrypting correct for tag too */ +            if (!EVP_CIPHER_CTX_encrypting(c)) { +                if (len < EVP_GCM_TLS_TAG_LEN) +                    return 0; +                len -= EVP_GCM_TLS_TAG_LEN; +            } +            EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; +            EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; +        } +        /* Extra padding: tag appended to record */ +        return EVP_GCM_TLS_TAG_LEN; + +    case EVP_CTRL_COPY: +        { +            EVP_CIPHER_CTX *out = ptr; +            EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out); +            if (gctx->gcm.key) { +                if (gctx->gcm.key != &gctx->ks) +                    return 0; +                gctx_out->gcm.key = &gctx_out->ks; +            } +            if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c)) +                gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out); +            else { +                gctx_out->iv = OPENSSL_malloc(gctx->ivlen); +                if (gctx_out->iv == NULL) +                    return 0; +                memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); +            } +            return 1; +        } + +    default: +        return -1; + +    } +} + +static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        do { +#ifdef HWAES_CAPABLE +            if (HWAES_CAPABLE) { +                HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &gctx->ks.ks); +                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, +                                   (block128_f) HWAES_encrypt); +# ifdef HWAES_ctr32_encrypt_blocks +                gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks; +# else +                gctx->ctr = NULL; +# endif +                break; +            } else +#endif +#ifdef BSAES_CAPABLE +            if (BSAES_CAPABLE) { +                AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &gctx->ks.ks); +                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, +                                   (block128_f) AES_encrypt); +                gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks; +                break; +            } else +#endif +#ifdef VPAES_CAPABLE +            if (VPAES_CAPABLE) { +                vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &gctx->ks.ks); +                CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, +                                   (block128_f) vpaes_encrypt); +                gctx->ctr = NULL; +                break; +            } else +#endif +                (void)0;        /* terminate potentially open 'else' */ + +            AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &gctx->ks.ks); +            CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, +                               (block128_f) AES_encrypt); +#ifdef AES_CTR_ASM +            gctx->ctr = (ctr128_f) AES_ctr32_encrypt; +#else +            gctx->ctr = NULL; +#endif +        } while (0); + +        /* +         * If we have an iv can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && gctx->iv_set) +            iv = gctx->iv; +        if (iv) { +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +            gctx->iv_set = 1; +        } +        gctx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (gctx->key_set) +            CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); +        else +            memcpy(gctx->iv, iv, gctx->ivlen); +        gctx->iv_set = 1; +        gctx->iv_gen = 0; +    } +    return 1; +} + +/* + * Handle TLS GCM packet format. This consists of the last portion of the IV + * followed by the payload and finally the tag. On encrypt generate IV, + * encrypt payload and write the tag. On verify retrieve IV, decrypt payload + * and verify tag. + */ + +static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +    int rv = -1; +    /* Encrypt/decrypt must be performed in place */ +    if (out != in +        || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) +        return -1; +    /* +     * Set IV from start of buffer or generate IV and write to start of +     * buffer. +     */ +    if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ? +                            EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, +                            EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) +        goto err; +    /* Use saved AAD */ +    if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), +                          gctx->tls_aad_len)) +        goto err; +    /* Fix buffer and length to point to payload */ +    in += EVP_GCM_TLS_EXPLICIT_IV_LEN; +    out += EVP_GCM_TLS_EXPLICIT_IV_LEN; +    len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        /* Encrypt payload */ +        if (gctx->ctr) { +            size_t bulk = 0; +#if defined(AES_GCM_ASM) +            if (len >= 32 && AES_GCM_ASM(gctx)) { +                if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0)) +                    return -1; + +                bulk = AES_gcm_encrypt(in, out, len, +                                       gctx->gcm.key, +                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                gctx->gcm.len.u[1] += bulk; +            } +#endif +            if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, +                                            in + bulk, +                                            out + bulk, +                                            len - bulk, gctx->ctr)) +                goto err; +        } else { +            size_t bulk = 0; +#if defined(AES_GCM_ASM2) +            if (len >= 32 && AES_GCM_ASM2(gctx)) { +                if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0)) +                    return -1; + +                bulk = AES_gcm_encrypt(in, out, len, +                                       gctx->gcm.key, +                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                gctx->gcm.len.u[1] += bulk; +            } +#endif +            if (CRYPTO_gcm128_encrypt(&gctx->gcm, +                                      in + bulk, out + bulk, len - bulk)) +                goto err; +        } +        out += len; +        /* Finally write tag */ +        CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); +        rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; +    } else { +        /* Decrypt */ +        if (gctx->ctr) { +            size_t bulk = 0; +#if defined(AES_GCM_ASM) +            if (len >= 16 && AES_GCM_ASM(gctx)) { +                if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0)) +                    return -1; + +                bulk = AES_gcm_decrypt(in, out, len, +                                       gctx->gcm.key, +                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                gctx->gcm.len.u[1] += bulk; +            } +#endif +            if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, +                                            in + bulk, +                                            out + bulk, +                                            len - bulk, gctx->ctr)) +                goto err; +        } else { +            size_t bulk = 0; +#if defined(AES_GCM_ASM2) +            if (len >= 16 && AES_GCM_ASM2(gctx)) { +                if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0)) +                    return -1; + +                bulk = AES_gcm_decrypt(in, out, len, +                                       gctx->gcm.key, +                                       gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                gctx->gcm.len.u[1] += bulk; +            } +#endif +            if (CRYPTO_gcm128_decrypt(&gctx->gcm, +                                      in + bulk, out + bulk, len - bulk)) +                goto err; +        } +        /* Retrieve tag */ +        CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), +                          EVP_GCM_TLS_TAG_LEN); +        /* If tag mismatch wipe buffer */ +        if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len, +                          EVP_GCM_TLS_TAG_LEN)) { +            OPENSSL_cleanse(out, len); +            goto err; +        } +        rv = len; +    } + + err: +    gctx->iv_set = 0; +    gctx->tls_aad_len = -1; +    return rv; +} + +static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); +    /* If not set up, return error */ +    if (!gctx->key_set) +        return -1; + +    if (gctx->tls_aad_len >= 0) +        return aes_gcm_tls_cipher(ctx, out, in, len); + +    if (!gctx->iv_set) +        return -1; +    if (in) { +        if (out == NULL) { +            if (CRYPTO_gcm128_aad(&gctx->gcm, in, len)) +                return -1; +        } else if (EVP_CIPHER_CTX_encrypting(ctx)) { +            if (gctx->ctr) { +                size_t bulk = 0; +#if defined(AES_GCM_ASM) +                if (len >= 32 && AES_GCM_ASM(gctx)) { +                    size_t res = (16 - gctx->gcm.mres) % 16; + +                    if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) +                        return -1; + +                    bulk = AES_gcm_encrypt(in + res, +                                           out + res, len - res, +                                           gctx->gcm.key, gctx->gcm.Yi.c, +                                           gctx->gcm.Xi.u); +                    gctx->gcm.len.u[1] += bulk; +                    bulk += res; +                } +#endif +                if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, +                                                in + bulk, +                                                out + bulk, +                                                len - bulk, gctx->ctr)) +                    return -1; +            } else { +                size_t bulk = 0; +#if defined(AES_GCM_ASM2) +                if (len >= 32 && AES_GCM_ASM2(gctx)) { +                    size_t res = (16 - gctx->gcm.mres) % 16; + +                    if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res)) +                        return -1; + +                    bulk = AES_gcm_encrypt(in + res, +                                           out + res, len - res, +                                           gctx->gcm.key, gctx->gcm.Yi.c, +                                           gctx->gcm.Xi.u); +                    gctx->gcm.len.u[1] += bulk; +                    bulk += res; +                } +#endif +                if (CRYPTO_gcm128_encrypt(&gctx->gcm, +                                          in + bulk, out + bulk, len - bulk)) +                    return -1; +            } +        } else { +            if (gctx->ctr) { +                size_t bulk = 0; +#if defined(AES_GCM_ASM) +                if (len >= 16 && AES_GCM_ASM(gctx)) { +                    size_t res = (16 - gctx->gcm.mres) % 16; + +                    if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) +                        return -1; + +                    bulk = AES_gcm_decrypt(in + res, +                                           out + res, len - res, +                                           gctx->gcm.key, +                                           gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                    gctx->gcm.len.u[1] += bulk; +                    bulk += res; +                } +#endif +                if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, +                                                in + bulk, +                                                out + bulk, +                                                len - bulk, gctx->ctr)) +                    return -1; +            } else { +                size_t bulk = 0; +#if defined(AES_GCM_ASM2) +                if (len >= 16 && AES_GCM_ASM2(gctx)) { +                    size_t res = (16 - gctx->gcm.mres) % 16; + +                    if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res)) +                        return -1; + +                    bulk = AES_gcm_decrypt(in + res, +                                           out + res, len - res, +                                           gctx->gcm.key, +                                           gctx->gcm.Yi.c, gctx->gcm.Xi.u); +                    gctx->gcm.len.u[1] += bulk; +                    bulk += res; +                } +#endif +                if (CRYPTO_gcm128_decrypt(&gctx->gcm, +                                          in + bulk, out + bulk, len - bulk)) +                    return -1; +            } +        } +        return len; +    } else { +        if (!EVP_CIPHER_CTX_encrypting(ctx)) { +            if (gctx->taglen < 0) +                return -1; +            if (CRYPTO_gcm128_finish(&gctx->gcm, +                                     EVP_CIPHER_CTX_buf_noconst(ctx), +                                     gctx->taglen) != 0) +                return -1; +            gctx->iv_set = 0; +            return 0; +        } +        CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16); +        gctx->taglen = 16; +        /* Don't reuse the IV */ +        gctx->iv_set = 0; +        return 0; +    } + +} + +#define CUSTOM_FLAGS    (EVP_CIPH_FLAG_DEFAULT_ASN1 \ +                | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ +                | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ +                | EVP_CIPH_CUSTOM_COPY) + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +    BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +    BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + +static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,c); +    if (type == EVP_CTRL_COPY) { +        EVP_CIPHER_CTX *out = ptr; +        EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out); +        if (xctx->xts.key1) { +            if (xctx->xts.key1 != &xctx->ks1) +                return 0; +            xctx_out->xts.key1 = &xctx_out->ks1; +        } +        if (xctx->xts.key2) { +            if (xctx->xts.key2 != &xctx->ks2) +                return 0; +            xctx_out->xts.key2 = &xctx_out->ks2; +        } +        return 1; +    } else if (type != EVP_CTRL_INIT) +        return -1; +    /* key1 and key2 are used as an indicator both key and IV are set */ +    xctx->xts.key1 = NULL; +    xctx->xts.key2 = NULL; +    return 1; +} + +static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); +    if (!iv && !key) +        return 1; + +    if (key) +        do { +#ifdef AES_XTS_ASM +            xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt; +#else +            xctx->stream = NULL; +#endif +            /* key_len is two AES keys */ +#ifdef HWAES_CAPABLE +            if (HWAES_CAPABLE) { +                if (enc) { +                    HWAES_set_encrypt_key(key, +                                          EVP_CIPHER_CTX_key_length(ctx) * 4, +                                          &xctx->ks1.ks); +                    xctx->xts.block1 = (block128_f) HWAES_encrypt; +# ifdef HWAES_xts_encrypt +                    xctx->stream = HWAES_xts_encrypt; +# endif +                } else { +                    HWAES_set_decrypt_key(key, +                                          EVP_CIPHER_CTX_key_length(ctx) * 4, +                                          &xctx->ks1.ks); +                    xctx->xts.block1 = (block128_f) HWAES_decrypt; +# ifdef HWAES_xts_decrypt +                    xctx->stream = HWAES_xts_decrypt; +#endif +                } + +                HWAES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, +                                      EVP_CIPHER_CTX_key_length(ctx) * 4, +                                      &xctx->ks2.ks); +                xctx->xts.block2 = (block128_f) HWAES_encrypt; + +                xctx->xts.key1 = &xctx->ks1; +                break; +            } else +#endif +#ifdef BSAES_CAPABLE +            if (BSAES_CAPABLE) +                xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt; +            else +#endif +#ifdef VPAES_CAPABLE +            if (VPAES_CAPABLE) { +                if (enc) { +                    vpaes_set_encrypt_key(key, +                                          EVP_CIPHER_CTX_key_length(ctx) * 4, +                                          &xctx->ks1.ks); +                    xctx->xts.block1 = (block128_f) vpaes_encrypt; +                } else { +                    vpaes_set_decrypt_key(key, +                                          EVP_CIPHER_CTX_key_length(ctx) * 4, +                                          &xctx->ks1.ks); +                    xctx->xts.block1 = (block128_f) vpaes_decrypt; +                } + +                vpaes_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, +                                      EVP_CIPHER_CTX_key_length(ctx) * 4, +                                      &xctx->ks2.ks); +                xctx->xts.block2 = (block128_f) vpaes_encrypt; + +                xctx->xts.key1 = &xctx->ks1; +                break; +            } else +#endif +                (void)0;        /* terminate potentially open 'else' */ + +            if (enc) { +                AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, +                                    &xctx->ks1.ks); +                xctx->xts.block1 = (block128_f) AES_encrypt; +            } else { +                AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4, +                                    &xctx->ks1.ks); +                xctx->xts.block1 = (block128_f) AES_decrypt; +            } + +            AES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2, +                                EVP_CIPHER_CTX_key_length(ctx) * 4, +                                &xctx->ks2.ks); +            xctx->xts.block2 = (block128_f) AES_encrypt; + +            xctx->xts.key1 = &xctx->ks1; +        } while (0); + +    if (iv) { +        xctx->xts.key2 = &xctx->ks2; +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); +    } + +    return 1; +} + +static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); +    if (!xctx->xts.key1 || !xctx->xts.key2) +        return 0; +    if (!out || !in || len < AES_BLOCK_SIZE) +        return 0; +    if (xctx->stream) +        (*xctx->stream) (in, out, len, +                         xctx->xts.key1, xctx->xts.key2, +                         EVP_CIPHER_CTX_iv_noconst(ctx)); +    else if (CRYPTO_xts128_encrypt(&xctx->xts, EVP_CIPHER_CTX_iv_noconst(ctx), +                                   in, out, len, +                                   EVP_CIPHER_CTX_encrypting(ctx))) +        return 0; +    return 1; +} + +#define aes_xts_cleanup NULL + +#define XTS_FLAGS       (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \ +                         | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ +                         | EVP_CIPH_CUSTOM_COPY) + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS) +    BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS) + +static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,c); +    switch (type) { +    case EVP_CTRL_INIT: +        cctx->key_set = 0; +        cctx->iv_set = 0; +        cctx->L = 8; +        cctx->M = 12; +        cctx->tag_set = 0; +        cctx->len_set = 0; +        cctx->tls_aad_len = -1; +        return 1; + +    case EVP_CTRL_AEAD_TLS1_AAD: +        /* Save the AAD for later use */ +        if (arg != EVP_AEAD_TLS1_AAD_LEN) +            return 0; +        memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); +        cctx->tls_aad_len = arg; +        { +            uint16_t len = +                EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 +                | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; +            /* Correct length for explicit IV */ +            if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN) +                return 0; +            len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; +            /* If decrypting correct for tag too */ +            if (!EVP_CIPHER_CTX_encrypting(c)) { +                if (len < cctx->M) +                    return 0; +                len -= cctx->M; +            } +            EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; +            EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; +        } +        /* Extra padding: tag appended to record */ +        return cctx->M; + +    case EVP_CTRL_CCM_SET_IV_FIXED: +        /* Sanity check length */ +        if (arg != EVP_CCM_TLS_FIXED_IV_LEN) +            return 0; +        /* Just copy to first part of IV */ +        memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg); +        return 1; + +    case EVP_CTRL_AEAD_SET_IVLEN: +        arg = 15 - arg; +        /* fall thru */ +    case EVP_CTRL_CCM_SET_L: +        if (arg < 2 || arg > 8) +            return 0; +        cctx->L = arg; +        return 1; + +    case EVP_CTRL_AEAD_SET_TAG: +        if ((arg & 1) || arg < 4 || arg > 16) +            return 0; +        if (EVP_CIPHER_CTX_encrypting(c) && ptr) +            return 0; +        if (ptr) { +            cctx->tag_set = 1; +            memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); +        } +        cctx->M = arg; +        return 1; + +    case EVP_CTRL_AEAD_GET_TAG: +        if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set) +            return 0; +        if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg)) +            return 0; +        cctx->tag_set = 0; +        cctx->iv_set = 0; +        cctx->len_set = 0; +        return 1; + +    case EVP_CTRL_COPY: +        { +            EVP_CIPHER_CTX *out = ptr; +            EVP_AES_CCM_CTX *cctx_out = EVP_C_DATA(EVP_AES_CCM_CTX,out); +            if (cctx->ccm.key) { +                if (cctx->ccm.key != &cctx->ks) +                    return 0; +                cctx_out->ccm.key = &cctx_out->ks; +            } +            return 1; +        } + +    default: +        return -1; + +    } +} + +static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) +        do { +#ifdef HWAES_CAPABLE +            if (HWAES_CAPABLE) { +                HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &cctx->ks.ks); + +                CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, +                                   &cctx->ks, (block128_f) HWAES_encrypt); +                cctx->str = NULL; +                cctx->key_set = 1; +                break; +            } else +#endif +#ifdef VPAES_CAPABLE +            if (VPAES_CAPABLE) { +                vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &cctx->ks.ks); +                CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, +                                   &cctx->ks, (block128_f) vpaes_encrypt); +                cctx->str = NULL; +                cctx->key_set = 1; +                break; +            } +#endif +            AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &cctx->ks.ks); +            CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, +                               &cctx->ks, (block128_f) AES_encrypt); +            cctx->str = NULL; +            cctx->key_set = 1; +        } while (0); +    if (iv) { +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); +        cctx->iv_set = 1; +    } +    return 1; +} + +static int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +    CCM128_CONTEXT *ccm = &cctx->ccm; +    /* Encrypt/decrypt must be performed in place */ +    if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M)) +        return -1; +    /* If encrypting set explicit IV from sequence number (start of AAD) */ +    if (EVP_CIPHER_CTX_encrypting(ctx)) +        memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx), +               EVP_CCM_TLS_EXPLICIT_IV_LEN); +    /* Get rest of IV from explicit IV */ +    memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in, +           EVP_CCM_TLS_EXPLICIT_IV_LEN); +    /* Correct length value */ +    len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; +    if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L, +                            len)) +            return -1; +    /* Use saved AAD */ +    CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len); +    /* Fix buffer to point to payload */ +    in += EVP_CCM_TLS_EXPLICIT_IV_LEN; +    out += EVP_CCM_TLS_EXPLICIT_IV_LEN; +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, +                                                    cctx->str) : +            CRYPTO_ccm128_encrypt(ccm, in, out, len)) +            return -1; +        if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M)) +            return -1; +        return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; +    } else { +        if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, +                                                     cctx->str) : +            !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { +            unsigned char tag[16]; +            if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { +                if (!CRYPTO_memcmp(tag, in + len, cctx->M)) +                    return len; +            } +        } +        OPENSSL_cleanse(out, len); +        return -1; +    } +} + +static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); +    CCM128_CONTEXT *ccm = &cctx->ccm; +    /* If not set up, return error */ +    if (!cctx->key_set) +        return -1; + +    if (cctx->tls_aad_len >= 0) +        return aes_ccm_tls_cipher(ctx, out, in, len); + +    if (!cctx->iv_set) +        return -1; + +    if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) +        return -1; +    if (!out) { +        if (!in) { +            if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), +                                    15 - cctx->L, len)) +                return -1; +            cctx->len_set = 1; +            return len; +        } +        /* If have AAD need message length */ +        if (!cctx->len_set && len) +            return -1; +        CRYPTO_ccm128_aad(ccm, in, len); +        return len; +    } +    /* EVP_*Final() doesn't return any data */ +    if (!in) +        return 0; +    /* If not set length yet do it */ +    if (!cctx->len_set) { +        if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), +                                15 - cctx->L, len)) +            return -1; +        cctx->len_set = 1; +    } +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, +                                                    cctx->str) : +            CRYPTO_ccm128_encrypt(ccm, in, out, len)) +            return -1; +        cctx->tag_set = 1; +        return len; +    } else { +        int rv = -1; +        if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, +                                                     cctx->str) : +            !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { +            unsigned char tag[16]; +            if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { +                if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx), +                                   cctx->M)) +                    rv = len; +            } +        } +        if (rv == -1) +            OPENSSL_cleanse(out, len); +        cctx->iv_set = 0; +        cctx->tag_set = 0; +        cctx->len_set = 0; +        return rv; +    } +} + +#define aes_ccm_cleanup NULL + +BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +    BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM, +                        EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +    BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM, +                        EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) + +typedef struct { +    union { +        double align; +        AES_KEY ks; +    } ks; +    /* Indicates if IV has been set */ +    unsigned char *iv; +} EVP_AES_WRAP_CTX; + +static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc) +{ +    EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        if (EVP_CIPHER_CTX_encrypting(ctx)) +            AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &wctx->ks.ks); +        else +            AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &wctx->ks.ks); +        if (!iv) +            wctx->iv = NULL; +    } +    if (iv) { +        memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx)); +        wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx); +    } +    return 1; +} + +static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inlen) +{ +    EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx); +    size_t rv; +    /* AES wrap with padding has IV length of 4, without padding 8 */ +    int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4; +    /* No final operation so always return zero length */ +    if (!in) +        return 0; +    /* Input length must always be non-zero */ +    if (!inlen) +        return -1; +    /* If decrypting need at least 16 bytes and multiple of 8 */ +    if (!EVP_CIPHER_CTX_encrypting(ctx) && (inlen < 16 || inlen & 0x7)) +        return -1; +    /* If not padding input must be multiple of 8 */ +    if (!pad && inlen & 0x7) +        return -1; +    if (is_partially_overlapping(out, in, inlen)) { +        EVPerr(EVP_F_AES_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); +        return 0; +    } +    if (!out) { +        if (EVP_CIPHER_CTX_encrypting(ctx)) { +            /* If padding round up to multiple of 8 */ +            if (pad) +                inlen = (inlen + 7) / 8 * 8; +            /* 8 byte prefix */ +            return inlen + 8; +        } else { +            /* +             * If not padding output will be exactly 8 bytes smaller than +             * input. If padding it will be at least 8 bytes smaller but we +             * don't know how much. +             */ +            return inlen - 8; +        } +    } +    if (pad) { +        if (EVP_CIPHER_CTX_encrypting(ctx)) +            rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv, +                                     out, in, inlen, +                                     (block128_f) AES_encrypt); +        else +            rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv, +                                       out, in, inlen, +                                       (block128_f) AES_decrypt); +    } else { +        if (EVP_CIPHER_CTX_encrypting(ctx)) +            rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv, +                                 out, in, inlen, (block128_f) AES_encrypt); +        else +            rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv, +                                   out, in, inlen, (block128_f) AES_decrypt); +    } +    return rv ? (int)rv : -1; +} + +#define WRAP_FLAGS      (EVP_CIPH_WRAP_MODE \ +                | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ +                | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1) + +static const EVP_CIPHER aes_128_wrap = { +    NID_id_aes128_wrap, +    8, 16, 8, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_128_wrap(void) +{ +    return &aes_128_wrap; +} + +static const EVP_CIPHER aes_192_wrap = { +    NID_id_aes192_wrap, +    8, 24, 8, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_192_wrap(void) +{ +    return &aes_192_wrap; +} + +static const EVP_CIPHER aes_256_wrap = { +    NID_id_aes256_wrap, +    8, 32, 8, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_256_wrap(void) +{ +    return &aes_256_wrap; +} + +static const EVP_CIPHER aes_128_wrap_pad = { +    NID_id_aes128_wrap_pad, +    8, 16, 4, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_128_wrap_pad(void) +{ +    return &aes_128_wrap_pad; +} + +static const EVP_CIPHER aes_192_wrap_pad = { +    NID_id_aes192_wrap_pad, +    8, 24, 4, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_192_wrap_pad(void) +{ +    return &aes_192_wrap_pad; +} + +static const EVP_CIPHER aes_256_wrap_pad = { +    NID_id_aes256_wrap_pad, +    8, 32, 4, WRAP_FLAGS, +    aes_wrap_init_key, aes_wrap_cipher, +    NULL, +    sizeof(EVP_AES_WRAP_CTX), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_aes_256_wrap_pad(void) +{ +    return &aes_256_wrap_pad; +} + +#ifndef OPENSSL_NO_OCB +static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c); +    EVP_CIPHER_CTX *newc; +    EVP_AES_OCB_CTX *new_octx; + +    switch (type) { +    case EVP_CTRL_INIT: +        octx->key_set = 0; +        octx->iv_set = 0; +        octx->ivlen = EVP_CIPHER_CTX_iv_length(c); +        octx->iv = EVP_CIPHER_CTX_iv_noconst(c); +        octx->taglen = 16; +        octx->data_buf_len = 0; +        octx->aad_buf_len = 0; +        return 1; + +    case EVP_CTRL_AEAD_SET_IVLEN: +        /* IV len must be 1 to 15 */ +        if (arg <= 0 || arg > 15) +            return 0; + +        octx->ivlen = arg; +        return 1; + +    case EVP_CTRL_AEAD_SET_TAG: +        if (!ptr) { +            /* Tag len must be 0 to 16 */ +            if (arg < 0 || arg > 16) +                return 0; + +            octx->taglen = arg; +            return 1; +        } +        if (arg != octx->taglen || EVP_CIPHER_CTX_encrypting(c)) +            return 0; +        memcpy(octx->tag, ptr, arg); +        return 1; + +    case EVP_CTRL_AEAD_GET_TAG: +        if (arg != octx->taglen || !EVP_CIPHER_CTX_encrypting(c)) +            return 0; + +        memcpy(ptr, octx->tag, arg); +        return 1; + +    case EVP_CTRL_COPY: +        newc = (EVP_CIPHER_CTX *)ptr; +        new_octx = EVP_C_DATA(EVP_AES_OCB_CTX,newc); +        return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb, +                                      &new_octx->ksenc.ks, +                                      &new_octx->ksdec.ks); + +    default: +        return -1; + +    } +} + +# ifdef HWAES_CAPABLE +#  ifdef HWAES_ocb_encrypt +void HWAES_ocb_encrypt(const unsigned char *in, unsigned char *out, +                       size_t blocks, const void *key, +                       size_t start_block_num, +                       unsigned char offset_i[16], +                       const unsigned char L_[][16], +                       unsigned char checksum[16]); +#  else +#    define HWAES_ocb_encrypt ((ocb128_f)NULL) +#  endif +#  ifdef HWAES_ocb_decrypt +void HWAES_ocb_decrypt(const unsigned char *in, unsigned char *out, +                       size_t blocks, const void *key, +                       size_t start_block_num, +                       unsigned char offset_i[16], +                       const unsigned char L_[][16], +                       unsigned char checksum[16]); +#  else +#    define HWAES_ocb_decrypt ((ocb128_f)NULL) +#  endif +# endif + +static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); +    if (!iv && !key) +        return 1; +    if (key) { +        do { +            /* +             * We set both the encrypt and decrypt key here because decrypt +             * needs both. We could possibly optimise to remove setting the +             * decrypt for an encryption operation. +             */ +# ifdef HWAES_CAPABLE +            if (HWAES_CAPABLE) { +                HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &octx->ksenc.ks); +                HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &octx->ksdec.ks); +                if (!CRYPTO_ocb128_init(&octx->ocb, +                                        &octx->ksenc.ks, &octx->ksdec.ks, +                                        (block128_f) HWAES_encrypt, +                                        (block128_f) HWAES_decrypt, +                                        enc ? HWAES_ocb_encrypt +                                            : HWAES_ocb_decrypt)) +                    return 0; +                break; +            } +# endif +# ifdef VPAES_CAPABLE +            if (VPAES_CAPABLE) { +                vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &octx->ksenc.ks); +                vpaes_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                      &octx->ksdec.ks); +                if (!CRYPTO_ocb128_init(&octx->ocb, +                                        &octx->ksenc.ks, &octx->ksdec.ks, +                                        (block128_f) vpaes_encrypt, +                                        (block128_f) vpaes_decrypt, +                                        NULL)) +                    return 0; +                break; +            } +# endif +            AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &octx->ksenc.ks); +            AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, +                                &octx->ksdec.ks); +            if (!CRYPTO_ocb128_init(&octx->ocb, +                                    &octx->ksenc.ks, &octx->ksdec.ks, +                                    (block128_f) AES_encrypt, +                                    (block128_f) AES_decrypt, +                                    NULL)) +                return 0; +        } +        while (0); + +        /* +         * If we have an iv we can set it directly, otherwise use saved IV. +         */ +        if (iv == NULL && octx->iv_set) +            iv = octx->iv; +        if (iv) { +            if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) +                != 1) +                return 0; +            octx->iv_set = 1; +        } +        octx->key_set = 1; +    } else { +        /* If key set use IV, otherwise copy */ +        if (octx->key_set) +            CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); +        else +            memcpy(octx->iv, iv, octx->ivlen); +        octx->iv_set = 1; +    } +    return 1; +} + +static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t len) +{ +    unsigned char *buf; +    int *buf_len; +    int written_len = 0; +    size_t trailing_len; +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); + +    /* If IV or Key not set then return error */ +    if (!octx->iv_set) +        return -1; + +    if (!octx->key_set) +        return -1; + +    if (in != NULL) { +        /* +         * Need to ensure we are only passing full blocks to low level OCB +         * routines. We do it here rather than in EVP_EncryptUpdate/ +         * EVP_DecryptUpdate because we need to pass full blocks of AAD too +         * and those routines don't support that +         */ + +        /* Are we dealing with AAD or normal data here? */ +        if (out == NULL) { +            buf = octx->aad_buf; +            buf_len = &(octx->aad_buf_len); +        } else { +            buf = octx->data_buf; +            buf_len = &(octx->data_buf_len); + +            if (is_partially_overlapping(out + *buf_len, in, len)) { +                EVPerr(EVP_F_AES_OCB_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); +                return 0; +            } +        } + +        /* +         * If we've got a partially filled buffer from a previous call then +         * use that data first +         */ +        if (*buf_len > 0) { +            unsigned int remaining; + +            remaining = AES_BLOCK_SIZE - (*buf_len); +            if (remaining > len) { +                memcpy(buf + (*buf_len), in, len); +                *(buf_len) += len; +                return 0; +            } +            memcpy(buf + (*buf_len), in, remaining); + +            /* +             * If we get here we've filled the buffer, so process it +             */ +            len -= remaining; +            in += remaining; +            if (out == NULL) { +                if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE)) +                    return -1; +            } else if (EVP_CIPHER_CTX_encrypting(ctx)) { +                if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, +                                           AES_BLOCK_SIZE)) +                    return -1; +            } else { +                if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, +                                           AES_BLOCK_SIZE)) +                    return -1; +            } +            written_len = AES_BLOCK_SIZE; +            *buf_len = 0; +            if (out != NULL) +                out += AES_BLOCK_SIZE; +        } + +        /* Do we have a partial block to handle at the end? */ +        trailing_len = len % AES_BLOCK_SIZE; + +        /* +         * If we've got some full blocks to handle, then process these first +         */ +        if (len != trailing_len) { +            if (out == NULL) { +                if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len)) +                    return -1; +            } else if (EVP_CIPHER_CTX_encrypting(ctx)) { +                if (!CRYPTO_ocb128_encrypt +                    (&octx->ocb, in, out, len - trailing_len)) +                    return -1; +            } else { +                if (!CRYPTO_ocb128_decrypt +                    (&octx->ocb, in, out, len - trailing_len)) +                    return -1; +            } +            written_len += len - trailing_len; +            in += len - trailing_len; +        } + +        /* Handle any trailing partial block */ +        if (trailing_len > 0) { +            memcpy(buf, in, trailing_len); +            *buf_len = trailing_len; +        } + +        return written_len; +    } else { +        /* +         * First of all empty the buffer of any partial block that we might +         * have been provided - both for data and AAD +         */ +        if (octx->data_buf_len > 0) { +            if (EVP_CIPHER_CTX_encrypting(ctx)) { +                if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out, +                                           octx->data_buf_len)) +                    return -1; +            } else { +                if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out, +                                           octx->data_buf_len)) +                    return -1; +            } +            written_len = octx->data_buf_len; +            octx->data_buf_len = 0; +        } +        if (octx->aad_buf_len > 0) { +            if (!CRYPTO_ocb128_aad +                (&octx->ocb, octx->aad_buf, octx->aad_buf_len)) +                return -1; +            octx->aad_buf_len = 0; +        } +        /* If decrypting then verify */ +        if (!EVP_CIPHER_CTX_encrypting(ctx)) { +            if (octx->taglen < 0) +                return -1; +            if (CRYPTO_ocb128_finish(&octx->ocb, +                                     octx->tag, octx->taglen) != 0) +                return -1; +            octx->iv_set = 0; +            return written_len; +        } +        /* If encrypting then just get the tag */ +        if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1) +            return -1; +        /* Don't reuse the IV */ +        octx->iv_set = 0; +        return written_len; +    } +} + +static int aes_ocb_cleanup(EVP_CIPHER_CTX *c) +{ +    EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c); +    CRYPTO_ocb128_cleanup(&octx->ocb); +    return 1; +} + +BLOCK_CIPHER_custom(NID_aes, 128, 16, 12, ocb, OCB, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +BLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +BLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB, +                    EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) +#endif                         /* OPENSSL_NO_OCB */ diff --git a/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha1.c b/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha1.c new file mode 100644 index 0000000..f30f722 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -0,0 +1,964 @@ +/* + * Copyright 2011-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> + +#include <stdio.h> +#include <string.h> + +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/aes.h> +#include <openssl/sha.h> +#include <openssl/rand.h> +#include "modes_lcl.h" +#include "internal/evp_int.h" +#include "internal/constant_time_locl.h" + +typedef struct { +    AES_KEY ks; +    SHA_CTX head, tail, md; +    size_t payload_length;      /* AAD length in decrypt case */ +    union { +        unsigned int tls_ver; +        unsigned char tls_aad[16]; /* 13 used */ +    } aux; +} EVP_AES_HMAC_SHA1; + +#define NO_PAYLOAD_LENGTH       ((size_t)-1) + +#if     defined(AES_ASM) &&     ( \ +        defined(__x86_64)       || defined(__x86_64__)  || \ +        defined(_M_AMD64)       || defined(_M_X64)      ) + +extern unsigned int OPENSSL_ia32cap_P[]; +# define AESNI_CAPABLE   (1<<(57-32)) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); + +void aesni_cbc_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key, unsigned char *ivec, int enc); + +void aesni_cbc_sha1_enc(const void *inp, void *out, size_t blocks, +                        const AES_KEY *key, unsigned char iv[16], +                        SHA_CTX *ctx, const void *in0); + +void aesni256_cbc_sha1_dec(const void *inp, void *out, size_t blocks, +                           const AES_KEY *key, unsigned char iv[16], +                           SHA_CTX *ctx, const void *in0); + +# define data(ctx) ((EVP_AES_HMAC_SHA1 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, +                                        const unsigned char *inkey, +                                        const unsigned char *iv, int enc) +{ +    EVP_AES_HMAC_SHA1 *key = data(ctx); +    int ret; + +    if (enc) +        ret = aesni_set_encrypt_key(inkey, +                                    EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &key->ks); +    else +        ret = aesni_set_decrypt_key(inkey, +                                    EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &key->ks); + +    SHA1_Init(&key->head);      /* handy when benchmarking */ +    key->tail = key->head; +    key->md = key->head; + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    return ret < 0 ? 0 : 1; +} + +# define STITCHED_CALL +# undef  STITCHED_DECRYPT_CALL + +# if !defined(STITCHED_CALL) +#  define aes_off 0 +# endif + +void sha1_block_data_order(void *c, const void *p, size_t len); + +static void sha1_update(SHA_CTX *c, const void *data, size_t len) +{ +    const unsigned char *ptr = data; +    size_t res; + +    if ((res = c->num)) { +        res = SHA_CBLOCK - res; +        if (len < res) +            res = len; +        SHA1_Update(c, ptr, res); +        ptr += res; +        len -= res; +    } + +    res = len % SHA_CBLOCK; +    len -= res; + +    if (len) { +        sha1_block_data_order(c, ptr, len / SHA_CBLOCK); + +        ptr += len; +        c->Nh += len >> 29; +        c->Nl += len <<= 3; +        if (c->Nl < (unsigned int)len) +            c->Nh++; +    } + +    if (res) +        SHA1_Update(c, ptr, res); +} + +# ifdef SHA1_Update +#  undef SHA1_Update +# endif +# define SHA1_Update sha1_update + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { +    unsigned int A[8], B[8], C[8], D[8], E[8]; +} SHA1_MB_CTX; +typedef struct { +    const unsigned char *ptr; +    int blocks; +} HASH_DESC; + +void sha1_multi_block(SHA1_MB_CTX *, const HASH_DESC *, int); + +typedef struct { +    const unsigned char *inp; +    unsigned char *out; +    int blocks; +    u64 iv[2]; +} CIPH_DESC; + +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA1 *key, +                                         unsigned char *out, +                                         const unsigned char *inp, +                                         size_t inp_len, int n4x) +{                               /* n4x is 1 or 2 */ +    HASH_DESC hash_d[8], edges[8]; +    CIPH_DESC ciph_d[8]; +    unsigned char storage[sizeof(SHA1_MB_CTX) + 32]; +    union { +        u64 q[16]; +        u32 d[32]; +        u8 c[128]; +    } blocks[8]; +    SHA1_MB_CTX *ctx; +    unsigned int frag, last, packlen, i, x4 = 4 * n4x, minblocks, processed = +        0; +    size_t ret = 0; +    u8 *IVs; +#  if defined(BSWAP8) +    u64 seqnum; +#  endif + +    /* ask for IVs in bulk */ +    if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0) +        return 0; + +    ctx = (SHA1_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); /* align */ + +    frag = (unsigned int)inp_len >> (1 + n4x); +    last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); +    if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { +        frag++; +        last -= x4 - 1; +    } + +    packlen = 5 + 16 + ((frag + 20 + 16) & -16); + +    /* populate descriptors with pointers and IVs */ +    hash_d[0].ptr = inp; +    ciph_d[0].inp = inp; +    /* 5+16 is place for header and explicit IV */ +    ciph_d[0].out = out + 5 + 16; +    memcpy(ciph_d[0].out - 16, IVs, 16); +    memcpy(ciph_d[0].iv, IVs, 16); +    IVs += 16; + +    for (i = 1; i < x4; i++) { +        ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; +        ciph_d[i].out = ciph_d[i - 1].out + packlen; +        memcpy(ciph_d[i].out - 16, IVs, 16); +        memcpy(ciph_d[i].iv, IVs, 16); +        IVs += 16; +    } + +#  if defined(BSWAP8) +    memcpy(blocks[0].c, key->md.data, 8); +    seqnum = BSWAP8(blocks[0].q[0]); +#  endif +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag); +#  if !defined(BSWAP8) +        unsigned int carry, j; +#  endif + +        ctx->A[i] = key->md.h0; +        ctx->B[i] = key->md.h1; +        ctx->C[i] = key->md.h2; +        ctx->D[i] = key->md.h3; +        ctx->E[i] = key->md.h4; + +        /* fix seqnum */ +#  if defined(BSWAP8) +        blocks[i].q[0] = BSWAP8(seqnum + i); +#  else +        for (carry = i, j = 8; j--;) { +            blocks[i].c[j] = ((u8 *)key->md.data)[j] + carry; +            carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); +        } +#  endif +        blocks[i].c[8] = ((u8 *)key->md.data)[8]; +        blocks[i].c[9] = ((u8 *)key->md.data)[9]; +        blocks[i].c[10] = ((u8 *)key->md.data)[10]; +        /* fix length */ +        blocks[i].c[11] = (u8)(len >> 8); +        blocks[i].c[12] = (u8)(len); + +        memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); +        hash_d[i].ptr += 64 - 13; +        hash_d[i].blocks = (len - (64 - 13)) / 64; + +        edges[i].ptr = blocks[i].c; +        edges[i].blocks = 1; +    } + +    /* hash 13-byte headers and first 64-13 bytes of inputs */ +    sha1_multi_block(ctx, edges, n4x); +    /* hash bulk inputs */ +#  define MAXCHUNKSIZE    2048 +#  if     MAXCHUNKSIZE%64 +#   error  "MAXCHUNKSIZE is not divisible by 64" +#  elif   MAXCHUNKSIZE +    /* +     * goal is to minimize pressure on L1 cache by moving in shorter steps, +     * so that hashed data is still in the cache by the time we encrypt it +     */ +    minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; +    if (minblocks > MAXCHUNKSIZE / 64) { +        for (i = 0; i < x4; i++) { +            edges[i].ptr = hash_d[i].ptr; +            edges[i].blocks = MAXCHUNKSIZE / 64; +            ciph_d[i].blocks = MAXCHUNKSIZE / 16; +        } +        do { +            sha1_multi_block(ctx, edges, n4x); +            aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + +            for (i = 0; i < x4; i++) { +                edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; +                hash_d[i].blocks -= MAXCHUNKSIZE / 64; +                edges[i].blocks = MAXCHUNKSIZE / 64; +                ciph_d[i].inp += MAXCHUNKSIZE; +                ciph_d[i].out += MAXCHUNKSIZE; +                ciph_d[i].blocks = MAXCHUNKSIZE / 16; +                memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); +            } +            processed += MAXCHUNKSIZE; +            minblocks -= MAXCHUNKSIZE / 64; +        } while (minblocks > MAXCHUNKSIZE / 64); +    } +#  endif +#  undef  MAXCHUNKSIZE +    sha1_multi_block(ctx, hash_d, n4x); + +    memset(blocks, 0, sizeof(blocks)); +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag), +            off = hash_d[i].blocks * 64; +        const unsigned char *ptr = hash_d[i].ptr + off; + +        off = (len - processed) - (64 - 13) - off; /* remainder actually */ +        memcpy(blocks[i].c, ptr, off); +        blocks[i].c[off] = 0x80; +        len += 64 + 13;         /* 64 is HMAC header */ +        len *= 8;               /* convert to bits */ +        if (off < (64 - 8)) { +#  ifdef BSWAP4 +            blocks[i].d[15] = BSWAP4(len); +#  else +            PUTU32(blocks[i].c + 60, len); +#  endif +            edges[i].blocks = 1; +        } else { +#  ifdef BSWAP4 +            blocks[i].d[31] = BSWAP4(len); +#  else +            PUTU32(blocks[i].c + 124, len); +#  endif +            edges[i].blocks = 2; +        } +        edges[i].ptr = blocks[i].c; +    } + +    /* hash input tails and finalize */ +    sha1_multi_block(ctx, edges, n4x); + +    memset(blocks, 0, sizeof(blocks)); +    for (i = 0; i < x4; i++) { +#  ifdef BSWAP4 +        blocks[i].d[0] = BSWAP4(ctx->A[i]); +        ctx->A[i] = key->tail.h0; +        blocks[i].d[1] = BSWAP4(ctx->B[i]); +        ctx->B[i] = key->tail.h1; +        blocks[i].d[2] = BSWAP4(ctx->C[i]); +        ctx->C[i] = key->tail.h2; +        blocks[i].d[3] = BSWAP4(ctx->D[i]); +        ctx->D[i] = key->tail.h3; +        blocks[i].d[4] = BSWAP4(ctx->E[i]); +        ctx->E[i] = key->tail.h4; +        blocks[i].c[20] = 0x80; +        blocks[i].d[15] = BSWAP4((64 + 20) * 8); +#  else +        PUTU32(blocks[i].c + 0, ctx->A[i]); +        ctx->A[i] = key->tail.h0; +        PUTU32(blocks[i].c + 4, ctx->B[i]); +        ctx->B[i] = key->tail.h1; +        PUTU32(blocks[i].c + 8, ctx->C[i]); +        ctx->C[i] = key->tail.h2; +        PUTU32(blocks[i].c + 12, ctx->D[i]); +        ctx->D[i] = key->tail.h3; +        PUTU32(blocks[i].c + 16, ctx->E[i]); +        ctx->E[i] = key->tail.h4; +        blocks[i].c[20] = 0x80; +        PUTU32(blocks[i].c + 60, (64 + 20) * 8); +#  endif +        edges[i].ptr = blocks[i].c; +        edges[i].blocks = 1; +    } + +    /* finalize MACs */ +    sha1_multi_block(ctx, edges, n4x); + +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; +        unsigned char *out0 = out; + +        memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); +        ciph_d[i].inp = ciph_d[i].out; + +        out += 5 + 16 + len; + +        /* write MAC */ +        PUTU32(out + 0, ctx->A[i]); +        PUTU32(out + 4, ctx->B[i]); +        PUTU32(out + 8, ctx->C[i]); +        PUTU32(out + 12, ctx->D[i]); +        PUTU32(out + 16, ctx->E[i]); +        out += 20; +        len += 20; + +        /* pad */ +        pad = 15 - len % 16; +        for (j = 0; j <= pad; j++) +            *(out++) = pad; +        len += pad + 1; + +        ciph_d[i].blocks = (len - processed) / 16; +        len += 16;              /* account for explicit iv */ + +        /* arrange header */ +        out0[0] = ((u8 *)key->md.data)[8]; +        out0[1] = ((u8 *)key->md.data)[9]; +        out0[2] = ((u8 *)key->md.data)[10]; +        out0[3] = (u8)(len >> 8); +        out0[4] = (u8)(len); + +        ret += len + 5; +        inp += frag; +    } + +    aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + +    OPENSSL_cleanse(blocks, sizeof(blocks)); +    OPENSSL_cleanse(ctx, sizeof(*ctx)); + +    return ret; +} +# endif + +static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                      const unsigned char *in, size_t len) +{ +    EVP_AES_HMAC_SHA1 *key = data(ctx); +    unsigned int l; +    size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and +                                                * later */ +        sha_off = 0; +# if defined(STITCHED_CALL) +    size_t aes_off = 0, blocks; + +    sha_off = SHA_CBLOCK - key->md.num; +# endif + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    if (len % AES_BLOCK_SIZE) +        return 0; + +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        if (plen == NO_PAYLOAD_LENGTH) +            plen = len; +        else if (len != +                 ((plen + SHA_DIGEST_LENGTH + +                   AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) +            return 0; +        else if (key->aux.tls_ver >= TLS1_1_VERSION) +            iv = AES_BLOCK_SIZE; + +# if defined(STITCHED_CALL) +        if (plen > (sha_off + iv) +            && (blocks = (plen - (sha_off + iv)) / SHA_CBLOCK)) { +            SHA1_Update(&key->md, in + iv, sha_off); + +            aesni_cbc_sha1_enc(in, out, blocks, &key->ks, +                               EVP_CIPHER_CTX_iv_noconst(ctx), +                               &key->md, in + iv + sha_off); +            blocks *= SHA_CBLOCK; +            aes_off += blocks; +            sha_off += blocks; +            key->md.Nh += blocks >> 29; +            key->md.Nl += blocks <<= 3; +            if (key->md.Nl < (unsigned int)blocks) +                key->md.Nh++; +        } else { +            sha_off = 0; +        } +# endif +        sha_off += iv; +        SHA1_Update(&key->md, in + sha_off, plen - sha_off); + +        if (plen != len) {      /* "TLS" mode of operation */ +            if (in != out) +                memcpy(out + aes_off, in + aes_off, plen - aes_off); + +            /* calculate HMAC and append it to payload */ +            SHA1_Final(out + plen, &key->md); +            key->md = key->tail; +            SHA1_Update(&key->md, out + plen, SHA_DIGEST_LENGTH); +            SHA1_Final(out + plen, &key->md); + +            /* pad the payload|hmac */ +            plen += SHA_DIGEST_LENGTH; +            for (l = len - plen - 1; plen < len; plen++) +                out[plen] = l; +            /* encrypt HMAC|padding at once */ +            aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, +                              &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); +        } else { +            aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, +                              &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); +        } +    } else { +        union { +            unsigned int u[SHA_DIGEST_LENGTH / sizeof(unsigned int)]; +            unsigned char c[32 + SHA_DIGEST_LENGTH]; +        } mac, *pmac; + +        /* arrange cache line alignment */ +        pmac = (void *)(((size_t)mac.c + 31) & ((size_t)0 - 32)); + +        if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ +            size_t inp_len, mask, j, i; +            unsigned int res, maxpad, pad, bitlen; +            int ret = 1; +            union { +                unsigned int u[SHA_LBLOCK]; +                unsigned char c[SHA_CBLOCK]; +            } *data = (void *)key->md.data; +# if defined(STITCHED_DECRYPT_CALL) +            unsigned char tail_iv[AES_BLOCK_SIZE]; +            int stitch = 0; +# endif + +            if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) +                >= TLS1_1_VERSION) { +                if (len < (AES_BLOCK_SIZE + SHA_DIGEST_LENGTH + 1)) +                    return 0; + +                /* omit explicit iv */ +                memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), in, AES_BLOCK_SIZE); + +                in += AES_BLOCK_SIZE; +                out += AES_BLOCK_SIZE; +                len -= AES_BLOCK_SIZE; +            } else if (len < (SHA_DIGEST_LENGTH + 1)) +                return 0; + +# if defined(STITCHED_DECRYPT_CALL) +            if (len >= 1024 && ctx->key_len == 32) { +                /* decrypt last block */ +                memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE, +                       AES_BLOCK_SIZE); +                aesni_cbc_encrypt(in + len - AES_BLOCK_SIZE, +                                  out + len - AES_BLOCK_SIZE, AES_BLOCK_SIZE, +                                  &key->ks, tail_iv, 0); +                stitch = 1; +            } else +# endif +                /* decrypt HMAC|padding at once */ +                aesni_cbc_encrypt(in, out, len, &key->ks, +                                  EVP_CIPHER_CTX_iv_noconst(ctx), 0); + +            /* figure out payload length */ +            pad = out[len - 1]; +            maxpad = len - (SHA_DIGEST_LENGTH + 1); +            maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); +            maxpad &= 255; + +            mask = constant_time_ge(maxpad, pad); +            ret &= mask; +            /* +             * If pad is invalid then we will fail the above test but we must +             * continue anyway because we are in constant time code. However, +             * we'll use the maxpad value instead of the supplied pad to make +             * sure we perform well defined pointer arithmetic. +             */ +            pad = constant_time_select(mask, pad, maxpad); + +            inp_len = len - (SHA_DIGEST_LENGTH + pad + 1); + +            key->aux.tls_aad[plen - 2] = inp_len >> 8; +            key->aux.tls_aad[plen - 1] = inp_len; + +            /* calculate HMAC */ +            key->md = key->head; +            SHA1_Update(&key->md, key->aux.tls_aad, plen); + +# if defined(STITCHED_DECRYPT_CALL) +            if (stitch) { +                blocks = (len - (256 + 32 + SHA_CBLOCK)) / SHA_CBLOCK; +                aes_off = len - AES_BLOCK_SIZE - blocks * SHA_CBLOCK; +                sha_off = SHA_CBLOCK - plen; + +                aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0); + +                SHA1_Update(&key->md, out, sha_off); +                aesni256_cbc_sha1_dec(in + aes_off, +                                      out + aes_off, blocks, &key->ks, +                                      ctx->iv, &key->md, out + sha_off); + +                sha_off += blocks *= SHA_CBLOCK; +                out += sha_off; +                len -= sha_off; +                inp_len -= sha_off; + +                key->md.Nl += (blocks << 3); /* at most 18 bits */ +                memcpy(ctx->iv, tail_iv, AES_BLOCK_SIZE); +            } +# endif + +# if 1 +            len -= SHA_DIGEST_LENGTH; /* amend mac */ +            if (len >= (256 + SHA_CBLOCK)) { +                j = (len - (256 + SHA_CBLOCK)) & (0 - SHA_CBLOCK); +                j += SHA_CBLOCK - key->md.num; +                SHA1_Update(&key->md, out, j); +                out += j; +                len -= j; +                inp_len -= j; +            } + +            /* but pretend as if we hashed padded payload */ +            bitlen = key->md.Nl + (inp_len << 3); /* at most 18 bits */ +#  ifdef BSWAP4 +            bitlen = BSWAP4(bitlen); +#  else +            mac.c[0] = 0; +            mac.c[1] = (unsigned char)(bitlen >> 16); +            mac.c[2] = (unsigned char)(bitlen >> 8); +            mac.c[3] = (unsigned char)bitlen; +            bitlen = mac.u[0]; +#  endif + +            pmac->u[0] = 0; +            pmac->u[1] = 0; +            pmac->u[2] = 0; +            pmac->u[3] = 0; +            pmac->u[4] = 0; + +            for (res = key->md.num, j = 0; j < len; j++) { +                size_t c = out[j]; +                mask = (j - inp_len) >> (sizeof(j) * 8 - 8); +                c &= mask; +                c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); +                data->c[res++] = (unsigned char)c; + +                if (res != SHA_CBLOCK) +                    continue; + +                /* j is not incremented yet */ +                mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); +                data->u[SHA_LBLOCK - 1] |= bitlen & mask; +                sha1_block_data_order(&key->md, data, 1); +                mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); +                pmac->u[0] |= key->md.h0 & mask; +                pmac->u[1] |= key->md.h1 & mask; +                pmac->u[2] |= key->md.h2 & mask; +                pmac->u[3] |= key->md.h3 & mask; +                pmac->u[4] |= key->md.h4 & mask; +                res = 0; +            } + +            for (i = res; i < SHA_CBLOCK; i++, j++) +                data->c[i] = 0; + +            if (res > SHA_CBLOCK - 8) { +                mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); +                data->u[SHA_LBLOCK - 1] |= bitlen & mask; +                sha1_block_data_order(&key->md, data, 1); +                mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); +                pmac->u[0] |= key->md.h0 & mask; +                pmac->u[1] |= key->md.h1 & mask; +                pmac->u[2] |= key->md.h2 & mask; +                pmac->u[3] |= key->md.h3 & mask; +                pmac->u[4] |= key->md.h4 & mask; + +                memset(data, 0, SHA_CBLOCK); +                j += 64; +            } +            data->u[SHA_LBLOCK - 1] = bitlen; +            sha1_block_data_order(&key->md, data, 1); +            mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); +            pmac->u[0] |= key->md.h0 & mask; +            pmac->u[1] |= key->md.h1 & mask; +            pmac->u[2] |= key->md.h2 & mask; +            pmac->u[3] |= key->md.h3 & mask; +            pmac->u[4] |= key->md.h4 & mask; + +#  ifdef BSWAP4 +            pmac->u[0] = BSWAP4(pmac->u[0]); +            pmac->u[1] = BSWAP4(pmac->u[1]); +            pmac->u[2] = BSWAP4(pmac->u[2]); +            pmac->u[3] = BSWAP4(pmac->u[3]); +            pmac->u[4] = BSWAP4(pmac->u[4]); +#  else +            for (i = 0; i < 5; i++) { +                res = pmac->u[i]; +                pmac->c[4 * i + 0] = (unsigned char)(res >> 24); +                pmac->c[4 * i + 1] = (unsigned char)(res >> 16); +                pmac->c[4 * i + 2] = (unsigned char)(res >> 8); +                pmac->c[4 * i + 3] = (unsigned char)res; +            } +#  endif +            len += SHA_DIGEST_LENGTH; +# else +            SHA1_Update(&key->md, out, inp_len); +            res = key->md.num; +            SHA1_Final(pmac->c, &key->md); + +            { +                unsigned int inp_blocks, pad_blocks; + +                /* but pretend as if we hashed padded payload */ +                inp_blocks = +                    1 + ((SHA_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); +                res += (unsigned int)(len - inp_len); +                pad_blocks = res / SHA_CBLOCK; +                res %= SHA_CBLOCK; +                pad_blocks += +                    1 + ((SHA_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); +                for (; inp_blocks < pad_blocks; inp_blocks++) +                    sha1_block_data_order(&key->md, data, 1); +            } +# endif +            key->md = key->tail; +            SHA1_Update(&key->md, pmac->c, SHA_DIGEST_LENGTH); +            SHA1_Final(pmac->c, &key->md); + +            /* verify HMAC */ +            out += inp_len; +            len -= inp_len; +# if 1 +            { +                unsigned char *p = out + len - 1 - maxpad - SHA_DIGEST_LENGTH; +                size_t off = out - p; +                unsigned int c, cmask; + +                maxpad += SHA_DIGEST_LENGTH; +                for (res = 0, i = 0, j = 0; j < maxpad; j++) { +                    c = p[j]; +                    cmask = +                        ((int)(j - off - SHA_DIGEST_LENGTH)) >> (sizeof(int) * +                                                                 8 - 1); +                    res |= (c ^ pad) & ~cmask; /* ... and padding */ +                    cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); +                    res |= (c ^ pmac->c[i]) & cmask; +                    i += 1 & cmask; +                } +                maxpad -= SHA_DIGEST_LENGTH; + +                res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); +                ret &= (int)~res; +            } +# else +            for (res = 0, i = 0; i < SHA_DIGEST_LENGTH; i++) +                res |= out[i] ^ pmac->c[i]; +            res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); +            ret &= (int)~res; + +            /* verify padding */ +            pad = (pad & ~res) | (maxpad & res); +            out = out + len - 1 - pad; +            for (res = 0, i = 0; i < pad; i++) +                res |= out[i] ^ pad; + +            res = (0 - res) >> (sizeof(res) * 8 - 1); +            ret &= (int)~res; +# endif +            return ret; +        } else { +# if defined(STITCHED_DECRYPT_CALL) +            if (len >= 1024 && ctx->key_len == 32) { +                if (sha_off %= SHA_CBLOCK) +                    blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK; +                else +                    blocks = (len - 2 * SHA_CBLOCK) / SHA_CBLOCK; +                aes_off = len - blocks * SHA_CBLOCK; + +                aesni_cbc_encrypt(in, out, aes_off, &key->ks, ctx->iv, 0); +                SHA1_Update(&key->md, out, sha_off); +                aesni256_cbc_sha1_dec(in + aes_off, +                                      out + aes_off, blocks, &key->ks, +                                      ctx->iv, &key->md, out + sha_off); + +                sha_off += blocks *= SHA_CBLOCK; +                out += sha_off; +                len -= sha_off; + +                key->md.Nh += blocks >> 29; +                key->md.Nl += blocks <<= 3; +                if (key->md.Nl < (unsigned int)blocks) +                    key->md.Nh++; +            } else +# endif +                /* decrypt HMAC|padding at once */ +                aesni_cbc_encrypt(in, out, len, &key->ks, +                                  EVP_CIPHER_CTX_iv_noconst(ctx), 0); + +            SHA1_Update(&key->md, out, len); +        } +    } + +    return 1; +} + +static int aesni_cbc_hmac_sha1_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, +                                    void *ptr) +{ +    EVP_AES_HMAC_SHA1 *key = data(ctx); + +    switch (type) { +    case EVP_CTRL_AEAD_SET_MAC_KEY: +        { +            unsigned int i; +            unsigned char hmac_key[64]; + +            memset(hmac_key, 0, sizeof(hmac_key)); + +            if (arg > (int)sizeof(hmac_key)) { +                SHA1_Init(&key->head); +                SHA1_Update(&key->head, ptr, arg); +                SHA1_Final(hmac_key, &key->head); +            } else { +                memcpy(hmac_key, ptr, arg); +            } + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36; /* ipad */ +            SHA1_Init(&key->head); +            SHA1_Update(&key->head, hmac_key, sizeof(hmac_key)); + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ +            SHA1_Init(&key->tail); +            SHA1_Update(&key->tail, hmac_key, sizeof(hmac_key)); + +            OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + +            return 1; +        } +    case EVP_CTRL_AEAD_TLS1_AAD: +        { +            unsigned char *p = ptr; +            unsigned int len; + +            if (arg != EVP_AEAD_TLS1_AAD_LEN) +                return -1; + +            len = p[arg - 2] << 8 | p[arg - 1]; + +            if (EVP_CIPHER_CTX_encrypting(ctx)) { +                key->payload_length = len; +                if ((key->aux.tls_ver = +                     p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { +                    if (len < AES_BLOCK_SIZE) +                        return 0; +                    len -= AES_BLOCK_SIZE; +                    p[arg - 2] = len >> 8; +                    p[arg - 1] = len; +                } +                key->md = key->head; +                SHA1_Update(&key->md, p, arg); + +                return (int)(((len + SHA_DIGEST_LENGTH + +                               AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) +                             - len); +            } else { +                memcpy(key->aux.tls_aad, ptr, arg); +                key->payload_length = arg; + +                return SHA_DIGEST_LENGTH; +            } +        } +# if !defined(OPENSSL_NO_MULTIBLOCK) +    case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE: +        return (int)(5 + 16 + ((arg + 20 + 16) & -16)); +    case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: +        { +            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = +                (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; +            unsigned int n4x = 1, x4; +            unsigned int frag, last, packlen, inp_len; + +            if (arg < (int)sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM)) +                return -1; + +            inp_len = param->inp[11] << 8 | param->inp[12]; + +            if (EVP_CIPHER_CTX_encrypting(ctx)) { +                if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) +                    return -1; + +                if (inp_len) { +                    if (inp_len < 4096) +                        return 0; /* too short */ + +                    if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) +                        n4x = 2; /* AVX2 */ +                } else if ((n4x = param->interleave / 4) && n4x <= 2) +                    inp_len = param->len; +                else +                    return -1; + +                key->md = key->head; +                SHA1_Update(&key->md, param->inp, 13); + +                x4 = 4 * n4x; +                n4x += 1; + +                frag = inp_len >> n4x; +                last = inp_len + frag - (frag << n4x); +                if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { +                    frag++; +                    last -= x4 - 1; +                } + +                packlen = 5 + 16 + ((frag + 20 + 16) & -16); +                packlen = (packlen << n4x) - packlen; +                packlen += 5 + 16 + ((last + 20 + 16) & -16); + +                param->interleave = x4; + +                return (int)packlen; +            } else +                return -1;      /* not yet */ +        } +    case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: +        { +            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = +                (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + +            return (int)tls1_1_multi_block_encrypt(key, param->out, +                                                   param->inp, param->len, +                                                   param->interleave / 4); +        } +    case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT: +# endif +    default: +        return -1; +    } +} + +static EVP_CIPHER aesni_128_cbc_hmac_sha1_cipher = { +# ifdef NID_aes_128_cbc_hmac_sha1 +    NID_aes_128_cbc_hmac_sha1, +# else +    NID_undef, +# endif +    AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE, +    EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | +        EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, +    aesni_cbc_hmac_sha1_init_key, +    aesni_cbc_hmac_sha1_cipher, +    NULL, +    sizeof(EVP_AES_HMAC_SHA1), +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, +    aesni_cbc_hmac_sha1_ctrl, +    NULL +}; + +static EVP_CIPHER aesni_256_cbc_hmac_sha1_cipher = { +# ifdef NID_aes_256_cbc_hmac_sha1 +    NID_aes_256_cbc_hmac_sha1, +# else +    NID_undef, +# endif +    AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE, +    EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | +        EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, +    aesni_cbc_hmac_sha1_init_key, +    aesni_cbc_hmac_sha1_cipher, +    NULL, +    sizeof(EVP_AES_HMAC_SHA1), +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, +    aesni_cbc_hmac_sha1_ctrl, +    NULL +}; + +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void) +{ +    return (OPENSSL_ia32cap_P[1] & AESNI_CAPABLE ? +            &aesni_128_cbc_hmac_sha1_cipher : NULL); +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void) +{ +    return (OPENSSL_ia32cap_P[1] & AESNI_CAPABLE ? +            &aesni_256_cbc_hmac_sha1_cipher : NULL); +} +#else +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void) +{ +    return NULL; +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void) +{ +    return NULL; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha256.c b/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha256.c new file mode 100644 index 0000000..13973f1 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_aes_cbc_hmac_sha256.c @@ -0,0 +1,950 @@ +/* + * Copyright 2013-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> + +#include <stdio.h> +#include <string.h> + + +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/aes.h> +#include <openssl/sha.h> +#include <openssl/rand.h> +#include "modes_lcl.h" +#include "internal/constant_time_locl.h" +#include "internal/evp_int.h" + +typedef struct { +    AES_KEY ks; +    SHA256_CTX head, tail, md; +    size_t payload_length;      /* AAD length in decrypt case */ +    union { +        unsigned int tls_ver; +        unsigned char tls_aad[16]; /* 13 used */ +    } aux; +} EVP_AES_HMAC_SHA256; + +# define NO_PAYLOAD_LENGTH       ((size_t)-1) + +#if     defined(AES_ASM) &&     ( \ +        defined(__x86_64)       || defined(__x86_64__)  || \ +        defined(_M_AMD64)       || defined(_M_X64)      ) + +extern unsigned int OPENSSL_ia32cap_P[]; +# define AESNI_CAPABLE   (1<<(57-32)) + +int aesni_set_encrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); +int aesni_set_decrypt_key(const unsigned char *userKey, int bits, +                          AES_KEY *key); + +void aesni_cbc_encrypt(const unsigned char *in, +                       unsigned char *out, +                       size_t length, +                       const AES_KEY *key, unsigned char *ivec, int enc); + +int aesni_cbc_sha256_enc(const void *inp, void *out, size_t blocks, +                         const AES_KEY *key, unsigned char iv[16], +                         SHA256_CTX *ctx, const void *in0); + +# define data(ctx) ((EVP_AES_HMAC_SHA256 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int aesni_cbc_hmac_sha256_init_key(EVP_CIPHER_CTX *ctx, +                                          const unsigned char *inkey, +                                          const unsigned char *iv, int enc) +{ +    EVP_AES_HMAC_SHA256 *key = data(ctx); +    int ret; + +    if (enc) +        ret = aesni_set_encrypt_key(inkey, +                                    EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &key->ks); +    else +        ret = aesni_set_decrypt_key(inkey, +                                    EVP_CIPHER_CTX_key_length(ctx) * 8, +                                    &key->ks); + +    SHA256_Init(&key->head);    /* handy when benchmarking */ +    key->tail = key->head; +    key->md = key->head; + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    return ret < 0 ? 0 : 1; +} + +# define STITCHED_CALL + +# if !defined(STITCHED_CALL) +#  define aes_off 0 +# endif + +void sha256_block_data_order(void *c, const void *p, size_t len); + +static void sha256_update(SHA256_CTX *c, const void *data, size_t len) +{ +    const unsigned char *ptr = data; +    size_t res; + +    if ((res = c->num)) { +        res = SHA256_CBLOCK - res; +        if (len < res) +            res = len; +        SHA256_Update(c, ptr, res); +        ptr += res; +        len -= res; +    } + +    res = len % SHA256_CBLOCK; +    len -= res; + +    if (len) { +        sha256_block_data_order(c, ptr, len / SHA256_CBLOCK); + +        ptr += len; +        c->Nh += len >> 29; +        c->Nl += len <<= 3; +        if (c->Nl < (unsigned int)len) +            c->Nh++; +    } + +    if (res) +        SHA256_Update(c, ptr, res); +} + +# ifdef SHA256_Update +#  undef SHA256_Update +# endif +# define SHA256_Update sha256_update + +# if !defined(OPENSSL_NO_MULTIBLOCK) + +typedef struct { +    unsigned int A[8], B[8], C[8], D[8], E[8], F[8], G[8], H[8]; +} SHA256_MB_CTX; +typedef struct { +    const unsigned char *ptr; +    int blocks; +} HASH_DESC; + +void sha256_multi_block(SHA256_MB_CTX *, const HASH_DESC *, int); + +typedef struct { +    const unsigned char *inp; +    unsigned char *out; +    int blocks; +    u64 iv[2]; +} CIPH_DESC; + +void aesni_multi_cbc_encrypt(CIPH_DESC *, void *, int); + +static size_t tls1_1_multi_block_encrypt(EVP_AES_HMAC_SHA256 *key, +                                         unsigned char *out, +                                         const unsigned char *inp, +                                         size_t inp_len, int n4x) +{                               /* n4x is 1 or 2 */ +    HASH_DESC hash_d[8], edges[8]; +    CIPH_DESC ciph_d[8]; +    unsigned char storage[sizeof(SHA256_MB_CTX) + 32]; +    union { +        u64 q[16]; +        u32 d[32]; +        u8 c[128]; +    } blocks[8]; +    SHA256_MB_CTX *ctx; +    unsigned int frag, last, packlen, i, x4 = 4 * n4x, minblocks, processed = +        0; +    size_t ret = 0; +    u8 *IVs; +#  if defined(BSWAP8) +    u64 seqnum; +#  endif + +    /* ask for IVs in bulk */ +    if (RAND_bytes((IVs = blocks[0].c), 16 * x4) <= 0) +        return 0; + +    /* align */ +    ctx = (SHA256_MB_CTX *) (storage + 32 - ((size_t)storage % 32)); + +    frag = (unsigned int)inp_len >> (1 + n4x); +    last = (unsigned int)inp_len + frag - (frag << (1 + n4x)); +    if (last > frag && ((last + 13 + 9) % 64) < (x4 - 1)) { +        frag++; +        last -= x4 - 1; +    } + +    packlen = 5 + 16 + ((frag + 32 + 16) & -16); + +    /* populate descriptors with pointers and IVs */ +    hash_d[0].ptr = inp; +    ciph_d[0].inp = inp; +    /* 5+16 is place for header and explicit IV */ +    ciph_d[0].out = out + 5 + 16; +    memcpy(ciph_d[0].out - 16, IVs, 16); +    memcpy(ciph_d[0].iv, IVs, 16); +    IVs += 16; + +    for (i = 1; i < x4; i++) { +        ciph_d[i].inp = hash_d[i].ptr = hash_d[i - 1].ptr + frag; +        ciph_d[i].out = ciph_d[i - 1].out + packlen; +        memcpy(ciph_d[i].out - 16, IVs, 16); +        memcpy(ciph_d[i].iv, IVs, 16); +        IVs += 16; +    } + +#  if defined(BSWAP8) +    memcpy(blocks[0].c, key->md.data, 8); +    seqnum = BSWAP8(blocks[0].q[0]); +#  endif +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag); +#  if !defined(BSWAP8) +        unsigned int carry, j; +#  endif + +        ctx->A[i] = key->md.h[0]; +        ctx->B[i] = key->md.h[1]; +        ctx->C[i] = key->md.h[2]; +        ctx->D[i] = key->md.h[3]; +        ctx->E[i] = key->md.h[4]; +        ctx->F[i] = key->md.h[5]; +        ctx->G[i] = key->md.h[6]; +        ctx->H[i] = key->md.h[7]; + +        /* fix seqnum */ +#  if defined(BSWAP8) +        blocks[i].q[0] = BSWAP8(seqnum + i); +#  else +        for (carry = i, j = 8; j--;) { +            blocks[i].c[j] = ((u8 *)key->md.data)[j] + carry; +            carry = (blocks[i].c[j] - carry) >> (sizeof(carry) * 8 - 1); +        } +#  endif +        blocks[i].c[8] = ((u8 *)key->md.data)[8]; +        blocks[i].c[9] = ((u8 *)key->md.data)[9]; +        blocks[i].c[10] = ((u8 *)key->md.data)[10]; +        /* fix length */ +        blocks[i].c[11] = (u8)(len >> 8); +        blocks[i].c[12] = (u8)(len); + +        memcpy(blocks[i].c + 13, hash_d[i].ptr, 64 - 13); +        hash_d[i].ptr += 64 - 13; +        hash_d[i].blocks = (len - (64 - 13)) / 64; + +        edges[i].ptr = blocks[i].c; +        edges[i].blocks = 1; +    } + +    /* hash 13-byte headers and first 64-13 bytes of inputs */ +    sha256_multi_block(ctx, edges, n4x); +    /* hash bulk inputs */ +#  define MAXCHUNKSIZE    2048 +#  if     MAXCHUNKSIZE%64 +#   error  "MAXCHUNKSIZE is not divisible by 64" +#  elif   MAXCHUNKSIZE +    /* +     * goal is to minimize pressure on L1 cache by moving in shorter steps, +     * so that hashed data is still in the cache by the time we encrypt it +     */ +    minblocks = ((frag <= last ? frag : last) - (64 - 13)) / 64; +    if (minblocks > MAXCHUNKSIZE / 64) { +        for (i = 0; i < x4; i++) { +            edges[i].ptr = hash_d[i].ptr; +            edges[i].blocks = MAXCHUNKSIZE / 64; +            ciph_d[i].blocks = MAXCHUNKSIZE / 16; +        } +        do { +            sha256_multi_block(ctx, edges, n4x); +            aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + +            for (i = 0; i < x4; i++) { +                edges[i].ptr = hash_d[i].ptr += MAXCHUNKSIZE; +                hash_d[i].blocks -= MAXCHUNKSIZE / 64; +                edges[i].blocks = MAXCHUNKSIZE / 64; +                ciph_d[i].inp += MAXCHUNKSIZE; +                ciph_d[i].out += MAXCHUNKSIZE; +                ciph_d[i].blocks = MAXCHUNKSIZE / 16; +                memcpy(ciph_d[i].iv, ciph_d[i].out - 16, 16); +            } +            processed += MAXCHUNKSIZE; +            minblocks -= MAXCHUNKSIZE / 64; +        } while (minblocks > MAXCHUNKSIZE / 64); +    } +#  endif +#  undef  MAXCHUNKSIZE +    sha256_multi_block(ctx, hash_d, n4x); + +    memset(blocks, 0, sizeof(blocks)); +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag), +            off = hash_d[i].blocks * 64; +        const unsigned char *ptr = hash_d[i].ptr + off; + +        off = (len - processed) - (64 - 13) - off; /* remainder actually */ +        memcpy(blocks[i].c, ptr, off); +        blocks[i].c[off] = 0x80; +        len += 64 + 13;         /* 64 is HMAC header */ +        len *= 8;               /* convert to bits */ +        if (off < (64 - 8)) { +#  ifdef BSWAP4 +            blocks[i].d[15] = BSWAP4(len); +#  else +            PUTU32(blocks[i].c + 60, len); +#  endif +            edges[i].blocks = 1; +        } else { +#  ifdef BSWAP4 +            blocks[i].d[31] = BSWAP4(len); +#  else +            PUTU32(blocks[i].c + 124, len); +#  endif +            edges[i].blocks = 2; +        } +        edges[i].ptr = blocks[i].c; +    } + +    /* hash input tails and finalize */ +    sha256_multi_block(ctx, edges, n4x); + +    memset(blocks, 0, sizeof(blocks)); +    for (i = 0; i < x4; i++) { +#  ifdef BSWAP4 +        blocks[i].d[0] = BSWAP4(ctx->A[i]); +        ctx->A[i] = key->tail.h[0]; +        blocks[i].d[1] = BSWAP4(ctx->B[i]); +        ctx->B[i] = key->tail.h[1]; +        blocks[i].d[2] = BSWAP4(ctx->C[i]); +        ctx->C[i] = key->tail.h[2]; +        blocks[i].d[3] = BSWAP4(ctx->D[i]); +        ctx->D[i] = key->tail.h[3]; +        blocks[i].d[4] = BSWAP4(ctx->E[i]); +        ctx->E[i] = key->tail.h[4]; +        blocks[i].d[5] = BSWAP4(ctx->F[i]); +        ctx->F[i] = key->tail.h[5]; +        blocks[i].d[6] = BSWAP4(ctx->G[i]); +        ctx->G[i] = key->tail.h[6]; +        blocks[i].d[7] = BSWAP4(ctx->H[i]); +        ctx->H[i] = key->tail.h[7]; +        blocks[i].c[32] = 0x80; +        blocks[i].d[15] = BSWAP4((64 + 32) * 8); +#  else +        PUTU32(blocks[i].c + 0, ctx->A[i]); +        ctx->A[i] = key->tail.h[0]; +        PUTU32(blocks[i].c + 4, ctx->B[i]); +        ctx->B[i] = key->tail.h[1]; +        PUTU32(blocks[i].c + 8, ctx->C[i]); +        ctx->C[i] = key->tail.h[2]; +        PUTU32(blocks[i].c + 12, ctx->D[i]); +        ctx->D[i] = key->tail.h[3]; +        PUTU32(blocks[i].c + 16, ctx->E[i]); +        ctx->E[i] = key->tail.h[4]; +        PUTU32(blocks[i].c + 20, ctx->F[i]); +        ctx->F[i] = key->tail.h[5]; +        PUTU32(blocks[i].c + 24, ctx->G[i]); +        ctx->G[i] = key->tail.h[6]; +        PUTU32(blocks[i].c + 28, ctx->H[i]); +        ctx->H[i] = key->tail.h[7]; +        blocks[i].c[32] = 0x80; +        PUTU32(blocks[i].c + 60, (64 + 32) * 8); +#  endif +        edges[i].ptr = blocks[i].c; +        edges[i].blocks = 1; +    } + +    /* finalize MACs */ +    sha256_multi_block(ctx, edges, n4x); + +    for (i = 0; i < x4; i++) { +        unsigned int len = (i == (x4 - 1) ? last : frag), pad, j; +        unsigned char *out0 = out; + +        memcpy(ciph_d[i].out, ciph_d[i].inp, len - processed); +        ciph_d[i].inp = ciph_d[i].out; + +        out += 5 + 16 + len; + +        /* write MAC */ +        PUTU32(out + 0, ctx->A[i]); +        PUTU32(out + 4, ctx->B[i]); +        PUTU32(out + 8, ctx->C[i]); +        PUTU32(out + 12, ctx->D[i]); +        PUTU32(out + 16, ctx->E[i]); +        PUTU32(out + 20, ctx->F[i]); +        PUTU32(out + 24, ctx->G[i]); +        PUTU32(out + 28, ctx->H[i]); +        out += 32; +        len += 32; + +        /* pad */ +        pad = 15 - len % 16; +        for (j = 0; j <= pad; j++) +            *(out++) = pad; +        len += pad + 1; + +        ciph_d[i].blocks = (len - processed) / 16; +        len += 16;              /* account for explicit iv */ + +        /* arrange header */ +        out0[0] = ((u8 *)key->md.data)[8]; +        out0[1] = ((u8 *)key->md.data)[9]; +        out0[2] = ((u8 *)key->md.data)[10]; +        out0[3] = (u8)(len >> 8); +        out0[4] = (u8)(len); + +        ret += len + 5; +        inp += frag; +    } + +    aesni_multi_cbc_encrypt(ciph_d, &key->ks, n4x); + +    OPENSSL_cleanse(blocks, sizeof(blocks)); +    OPENSSL_cleanse(ctx, sizeof(*ctx)); + +    return ret; +} +# endif + +static int aesni_cbc_hmac_sha256_cipher(EVP_CIPHER_CTX *ctx, +                                        unsigned char *out, +                                        const unsigned char *in, size_t len) +{ +    EVP_AES_HMAC_SHA256 *key = data(ctx); +    unsigned int l; +    size_t plen = key->payload_length, iv = 0, /* explicit IV in TLS 1.1 and +                                                * later */ +        sha_off = 0; +# if defined(STITCHED_CALL) +    size_t aes_off = 0, blocks; + +    sha_off = SHA256_CBLOCK - key->md.num; +# endif + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    if (len % AES_BLOCK_SIZE) +        return 0; + +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        if (plen == NO_PAYLOAD_LENGTH) +            plen = len; +        else if (len != +                 ((plen + SHA256_DIGEST_LENGTH + +                   AES_BLOCK_SIZE) & -AES_BLOCK_SIZE)) +            return 0; +        else if (key->aux.tls_ver >= TLS1_1_VERSION) +            iv = AES_BLOCK_SIZE; + +# if defined(STITCHED_CALL) +        /* +         * Assembly stitch handles AVX-capable processors, but its +         * performance is not optimal on AMD Jaguar, ~40% worse, for +         * unknown reasons. Incidentally processor in question supports +         * AVX, but not AMD-specific XOP extension, which can be used +         * to identify it and avoid stitch invocation. So that after we +         * establish that current CPU supports AVX, we even see if it's +         * either even XOP-capable Bulldozer-based or GenuineIntel one. +         * But SHAEXT-capable go ahead... +         */ +        if (((OPENSSL_ia32cap_P[2] & (1 << 29)) ||         /* SHAEXT? */ +             ((OPENSSL_ia32cap_P[1] & (1 << (60 - 32))) && /* AVX? */ +              ((OPENSSL_ia32cap_P[1] & (1 << (43 - 32)))   /* XOP? */ +               | (OPENSSL_ia32cap_P[0] & (1 << 30))))) &&  /* "Intel CPU"? */ +            plen > (sha_off + iv) && +            (blocks = (plen - (sha_off + iv)) / SHA256_CBLOCK)) { +            SHA256_Update(&key->md, in + iv, sha_off); + +            (void)aesni_cbc_sha256_enc(in, out, blocks, &key->ks, +                                       EVP_CIPHER_CTX_iv_noconst(ctx), +                                       &key->md, in + iv + sha_off); +            blocks *= SHA256_CBLOCK; +            aes_off += blocks; +            sha_off += blocks; +            key->md.Nh += blocks >> 29; +            key->md.Nl += blocks <<= 3; +            if (key->md.Nl < (unsigned int)blocks) +                key->md.Nh++; +        } else { +            sha_off = 0; +        } +# endif +        sha_off += iv; +        SHA256_Update(&key->md, in + sha_off, plen - sha_off); + +        if (plen != len) {      /* "TLS" mode of operation */ +            if (in != out) +                memcpy(out + aes_off, in + aes_off, plen - aes_off); + +            /* calculate HMAC and append it to payload */ +            SHA256_Final(out + plen, &key->md); +            key->md = key->tail; +            SHA256_Update(&key->md, out + plen, SHA256_DIGEST_LENGTH); +            SHA256_Final(out + plen, &key->md); + +            /* pad the payload|hmac */ +            plen += SHA256_DIGEST_LENGTH; +            for (l = len - plen - 1; plen < len; plen++) +                out[plen] = l; +            /* encrypt HMAC|padding at once */ +            aesni_cbc_encrypt(out + aes_off, out + aes_off, len - aes_off, +                              &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); +        } else { +            aesni_cbc_encrypt(in + aes_off, out + aes_off, len - aes_off, +                              &key->ks, EVP_CIPHER_CTX_iv_noconst(ctx), 1); +        } +    } else { +        union { +            unsigned int u[SHA256_DIGEST_LENGTH / sizeof(unsigned int)]; +            unsigned char c[64 + SHA256_DIGEST_LENGTH]; +        } mac, *pmac; + +        /* arrange cache line alignment */ +        pmac = (void *)(((size_t)mac.c + 63) & ((size_t)0 - 64)); + +        /* decrypt HMAC|padding at once */ +        aesni_cbc_encrypt(in, out, len, &key->ks, +                          EVP_CIPHER_CTX_iv_noconst(ctx), 0); + +        if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ +            size_t inp_len, mask, j, i; +            unsigned int res, maxpad, pad, bitlen; +            int ret = 1; +            union { +                unsigned int u[SHA_LBLOCK]; +                unsigned char c[SHA256_CBLOCK]; +            } *data = (void *)key->md.data; + +            if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) +                >= TLS1_1_VERSION) +                iv = AES_BLOCK_SIZE; + +            if (len < (iv + SHA256_DIGEST_LENGTH + 1)) +                return 0; + +            /* omit explicit iv */ +            out += iv; +            len -= iv; + +            /* figure out payload length */ +            pad = out[len - 1]; +            maxpad = len - (SHA256_DIGEST_LENGTH + 1); +            maxpad |= (255 - maxpad) >> (sizeof(maxpad) * 8 - 8); +            maxpad &= 255; + +            mask = constant_time_ge(maxpad, pad); +            ret &= mask; +            /* +             * If pad is invalid then we will fail the above test but we must +             * continue anyway because we are in constant time code. However, +             * we'll use the maxpad value instead of the supplied pad to make +             * sure we perform well defined pointer arithmetic. +             */ +            pad = constant_time_select(mask, pad, maxpad); + +            inp_len = len - (SHA256_DIGEST_LENGTH + pad + 1); + +            key->aux.tls_aad[plen - 2] = inp_len >> 8; +            key->aux.tls_aad[plen - 1] = inp_len; + +            /* calculate HMAC */ +            key->md = key->head; +            SHA256_Update(&key->md, key->aux.tls_aad, plen); + +# if 1 +            len -= SHA256_DIGEST_LENGTH; /* amend mac */ +            if (len >= (256 + SHA256_CBLOCK)) { +                j = (len - (256 + SHA256_CBLOCK)) & (0 - SHA256_CBLOCK); +                j += SHA256_CBLOCK - key->md.num; +                SHA256_Update(&key->md, out, j); +                out += j; +                len -= j; +                inp_len -= j; +            } + +            /* but pretend as if we hashed padded payload */ +            bitlen = key->md.Nl + (inp_len << 3); /* at most 18 bits */ +#  ifdef BSWAP4 +            bitlen = BSWAP4(bitlen); +#  else +            mac.c[0] = 0; +            mac.c[1] = (unsigned char)(bitlen >> 16); +            mac.c[2] = (unsigned char)(bitlen >> 8); +            mac.c[3] = (unsigned char)bitlen; +            bitlen = mac.u[0]; +#  endif + +            pmac->u[0] = 0; +            pmac->u[1] = 0; +            pmac->u[2] = 0; +            pmac->u[3] = 0; +            pmac->u[4] = 0; +            pmac->u[5] = 0; +            pmac->u[6] = 0; +            pmac->u[7] = 0; + +            for (res = key->md.num, j = 0; j < len; j++) { +                size_t c = out[j]; +                mask = (j - inp_len) >> (sizeof(j) * 8 - 8); +                c &= mask; +                c |= 0x80 & ~mask & ~((inp_len - j) >> (sizeof(j) * 8 - 8)); +                data->c[res++] = (unsigned char)c; + +                if (res != SHA256_CBLOCK) +                    continue; + +                /* j is not incremented yet */ +                mask = 0 - ((inp_len + 7 - j) >> (sizeof(j) * 8 - 1)); +                data->u[SHA_LBLOCK - 1] |= bitlen & mask; +                sha256_block_data_order(&key->md, data, 1); +                mask &= 0 - ((j - inp_len - 72) >> (sizeof(j) * 8 - 1)); +                pmac->u[0] |= key->md.h[0] & mask; +                pmac->u[1] |= key->md.h[1] & mask; +                pmac->u[2] |= key->md.h[2] & mask; +                pmac->u[3] |= key->md.h[3] & mask; +                pmac->u[4] |= key->md.h[4] & mask; +                pmac->u[5] |= key->md.h[5] & mask; +                pmac->u[6] |= key->md.h[6] & mask; +                pmac->u[7] |= key->md.h[7] & mask; +                res = 0; +            } + +            for (i = res; i < SHA256_CBLOCK; i++, j++) +                data->c[i] = 0; + +            if (res > SHA256_CBLOCK - 8) { +                mask = 0 - ((inp_len + 8 - j) >> (sizeof(j) * 8 - 1)); +                data->u[SHA_LBLOCK - 1] |= bitlen & mask; +                sha256_block_data_order(&key->md, data, 1); +                mask &= 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); +                pmac->u[0] |= key->md.h[0] & mask; +                pmac->u[1] |= key->md.h[1] & mask; +                pmac->u[2] |= key->md.h[2] & mask; +                pmac->u[3] |= key->md.h[3] & mask; +                pmac->u[4] |= key->md.h[4] & mask; +                pmac->u[5] |= key->md.h[5] & mask; +                pmac->u[6] |= key->md.h[6] & mask; +                pmac->u[7] |= key->md.h[7] & mask; + +                memset(data, 0, SHA256_CBLOCK); +                j += 64; +            } +            data->u[SHA_LBLOCK - 1] = bitlen; +            sha256_block_data_order(&key->md, data, 1); +            mask = 0 - ((j - inp_len - 73) >> (sizeof(j) * 8 - 1)); +            pmac->u[0] |= key->md.h[0] & mask; +            pmac->u[1] |= key->md.h[1] & mask; +            pmac->u[2] |= key->md.h[2] & mask; +            pmac->u[3] |= key->md.h[3] & mask; +            pmac->u[4] |= key->md.h[4] & mask; +            pmac->u[5] |= key->md.h[5] & mask; +            pmac->u[6] |= key->md.h[6] & mask; +            pmac->u[7] |= key->md.h[7] & mask; + +#  ifdef BSWAP4 +            pmac->u[0] = BSWAP4(pmac->u[0]); +            pmac->u[1] = BSWAP4(pmac->u[1]); +            pmac->u[2] = BSWAP4(pmac->u[2]); +            pmac->u[3] = BSWAP4(pmac->u[3]); +            pmac->u[4] = BSWAP4(pmac->u[4]); +            pmac->u[5] = BSWAP4(pmac->u[5]); +            pmac->u[6] = BSWAP4(pmac->u[6]); +            pmac->u[7] = BSWAP4(pmac->u[7]); +#  else +            for (i = 0; i < 8; i++) { +                res = pmac->u[i]; +                pmac->c[4 * i + 0] = (unsigned char)(res >> 24); +                pmac->c[4 * i + 1] = (unsigned char)(res >> 16); +                pmac->c[4 * i + 2] = (unsigned char)(res >> 8); +                pmac->c[4 * i + 3] = (unsigned char)res; +            } +#  endif +            len += SHA256_DIGEST_LENGTH; +# else +            SHA256_Update(&key->md, out, inp_len); +            res = key->md.num; +            SHA256_Final(pmac->c, &key->md); + +            { +                unsigned int inp_blocks, pad_blocks; + +                /* but pretend as if we hashed padded payload */ +                inp_blocks = +                    1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); +                res += (unsigned int)(len - inp_len); +                pad_blocks = res / SHA256_CBLOCK; +                res %= SHA256_CBLOCK; +                pad_blocks += +                    1 + ((SHA256_CBLOCK - 9 - res) >> (sizeof(res) * 8 - 1)); +                for (; inp_blocks < pad_blocks; inp_blocks++) +                    sha1_block_data_order(&key->md, data, 1); +            } +# endif +            key->md = key->tail; +            SHA256_Update(&key->md, pmac->c, SHA256_DIGEST_LENGTH); +            SHA256_Final(pmac->c, &key->md); + +            /* verify HMAC */ +            out += inp_len; +            len -= inp_len; +# if 1 +            { +                unsigned char *p = +                    out + len - 1 - maxpad - SHA256_DIGEST_LENGTH; +                size_t off = out - p; +                unsigned int c, cmask; + +                maxpad += SHA256_DIGEST_LENGTH; +                for (res = 0, i = 0, j = 0; j < maxpad; j++) { +                    c = p[j]; +                    cmask = +                        ((int)(j - off - SHA256_DIGEST_LENGTH)) >> +                        (sizeof(int) * 8 - 1); +                    res |= (c ^ pad) & ~cmask; /* ... and padding */ +                    cmask &= ((int)(off - 1 - j)) >> (sizeof(int) * 8 - 1); +                    res |= (c ^ pmac->c[i]) & cmask; +                    i += 1 & cmask; +                } +                maxpad -= SHA256_DIGEST_LENGTH; + +                res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); +                ret &= (int)~res; +            } +# else +            for (res = 0, i = 0; i < SHA256_DIGEST_LENGTH; i++) +                res |= out[i] ^ pmac->c[i]; +            res = 0 - ((0 - res) >> (sizeof(res) * 8 - 1)); +            ret &= (int)~res; + +            /* verify padding */ +            pad = (pad & ~res) | (maxpad & res); +            out = out + len - 1 - pad; +            for (res = 0, i = 0; i < pad; i++) +                res |= out[i] ^ pad; + +            res = (0 - res) >> (sizeof(res) * 8 - 1); +            ret &= (int)~res; +# endif +            return ret; +        } else { +            SHA256_Update(&key->md, out, len); +        } +    } + +    return 1; +} + +static int aesni_cbc_hmac_sha256_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, +                                      void *ptr) +{ +    EVP_AES_HMAC_SHA256 *key = data(ctx); +    unsigned int u_arg = (unsigned int)arg; + +    switch (type) { +    case EVP_CTRL_AEAD_SET_MAC_KEY: +        { +            unsigned int i; +            unsigned char hmac_key[64]; + +            memset(hmac_key, 0, sizeof(hmac_key)); + +            if (arg < 0) +                return -1; + +            if (u_arg > sizeof(hmac_key)) { +                SHA256_Init(&key->head); +                SHA256_Update(&key->head, ptr, arg); +                SHA256_Final(hmac_key, &key->head); +            } else { +                memcpy(hmac_key, ptr, arg); +            } + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36; /* ipad */ +            SHA256_Init(&key->head); +            SHA256_Update(&key->head, hmac_key, sizeof(hmac_key)); + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ +            SHA256_Init(&key->tail); +            SHA256_Update(&key->tail, hmac_key, sizeof(hmac_key)); + +            OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + +            return 1; +        } +    case EVP_CTRL_AEAD_TLS1_AAD: +        { +            unsigned char *p = ptr; +            unsigned int len; + +            if (arg != EVP_AEAD_TLS1_AAD_LEN) +                return -1; + +            len = p[arg - 2] << 8 | p[arg - 1]; + +            if (EVP_CIPHER_CTX_encrypting(ctx)) { +                key->payload_length = len; +                if ((key->aux.tls_ver = +                     p[arg - 4] << 8 | p[arg - 3]) >= TLS1_1_VERSION) { +                    if (len < AES_BLOCK_SIZE) +                        return 0; +                    len -= AES_BLOCK_SIZE; +                    p[arg - 2] = len >> 8; +                    p[arg - 1] = len; +                } +                key->md = key->head; +                SHA256_Update(&key->md, p, arg); + +                return (int)(((len + SHA256_DIGEST_LENGTH + +                               AES_BLOCK_SIZE) & -AES_BLOCK_SIZE) +                             - len); +            } else { +                memcpy(key->aux.tls_aad, ptr, arg); +                key->payload_length = arg; + +                return SHA256_DIGEST_LENGTH; +            } +        } +# if !defined(OPENSSL_NO_MULTIBLOCK) +    case EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE: +        return (int)(5 + 16 + ((arg + 32 + 16) & -16)); +    case EVP_CTRL_TLS1_1_MULTIBLOCK_AAD: +        { +            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = +                (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; +            unsigned int n4x = 1, x4; +            unsigned int frag, last, packlen, inp_len; + +            if (arg < 0) +                return -1; + +            if (u_arg < sizeof(EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM)) +                return -1; + +            inp_len = param->inp[11] << 8 | param->inp[12]; + +            if (EVP_CIPHER_CTX_encrypting(ctx)) { +                if ((param->inp[9] << 8 | param->inp[10]) < TLS1_1_VERSION) +                    return -1; + +                if (inp_len) { +                    if (inp_len < 4096) +                        return 0; /* too short */ + +                    if (inp_len >= 8192 && OPENSSL_ia32cap_P[2] & (1 << 5)) +                        n4x = 2; /* AVX2 */ +                } else if ((n4x = param->interleave / 4) && n4x <= 2) +                    inp_len = param->len; +                else +                    return -1; + +                key->md = key->head; +                SHA256_Update(&key->md, param->inp, 13); + +                x4 = 4 * n4x; +                n4x += 1; + +                frag = inp_len >> n4x; +                last = inp_len + frag - (frag << n4x); +                if (last > frag && ((last + 13 + 9) % 64 < (x4 - 1))) { +                    frag++; +                    last -= x4 - 1; +                } + +                packlen = 5 + 16 + ((frag + 32 + 16) & -16); +                packlen = (packlen << n4x) - packlen; +                packlen += 5 + 16 + ((last + 32 + 16) & -16); + +                param->interleave = x4; + +                return (int)packlen; +            } else +                return -1;      /* not yet */ +        } +    case EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT: +        { +            EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *param = +                (EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM *) ptr; + +            return (int)tls1_1_multi_block_encrypt(key, param->out, +                                                   param->inp, param->len, +                                                   param->interleave / 4); +        } +    case EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT: +# endif +    default: +        return -1; +    } +} + +static EVP_CIPHER aesni_128_cbc_hmac_sha256_cipher = { +# ifdef NID_aes_128_cbc_hmac_sha256 +    NID_aes_128_cbc_hmac_sha256, +# else +    NID_undef, +# endif +    AES_BLOCK_SIZE, 16, AES_BLOCK_SIZE, +    EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | +        EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, +    aesni_cbc_hmac_sha256_init_key, +    aesni_cbc_hmac_sha256_cipher, +    NULL, +    sizeof(EVP_AES_HMAC_SHA256), +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, +    aesni_cbc_hmac_sha256_ctrl, +    NULL +}; + +static EVP_CIPHER aesni_256_cbc_hmac_sha256_cipher = { +# ifdef NID_aes_256_cbc_hmac_sha256 +    NID_aes_256_cbc_hmac_sha256, +# else +    NID_undef, +# endif +    AES_BLOCK_SIZE, 32, AES_BLOCK_SIZE, +    EVP_CIPH_CBC_MODE | EVP_CIPH_FLAG_DEFAULT_ASN1 | +        EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK, +    aesni_cbc_hmac_sha256_init_key, +    aesni_cbc_hmac_sha256_cipher, +    NULL, +    sizeof(EVP_AES_HMAC_SHA256), +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_set_asn1_iv, +    EVP_CIPH_FLAG_DEFAULT_ASN1 ? NULL : EVP_CIPHER_get_asn1_iv, +    aesni_cbc_hmac_sha256_ctrl, +    NULL +}; + +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void) +{ +    return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) && +            aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ? +            &aesni_128_cbc_hmac_sha256_cipher : NULL); +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void) +{ +    return ((OPENSSL_ia32cap_P[1] & AESNI_CAPABLE) && +            aesni_cbc_sha256_enc(NULL, NULL, 0, NULL, NULL, NULL, NULL) ? +            &aesni_256_cbc_hmac_sha256_cipher : NULL); +} +#else +const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void) +{ +    return NULL; +} + +const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void) +{ +    return NULL; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_bf.c b/openssl-1.1.0h/crypto/evp/e_bf.c new file mode 100644 index 0000000..dc38690 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_bf.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" +#ifndef OPENSSL_NO_BF +# include <openssl/evp.h> +# include "internal/evp_int.h" +# include <openssl/objects.h> +# include <openssl/blowfish.h> + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                       const unsigned char *iv, int enc); + +typedef struct { +    BF_KEY ks; +} EVP_BF_KEY; + +# define data(ctx)       EVP_C_DATA(EVP_BF_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(bf, ks, BF, EVP_BF_KEY, NID_bf, 8, 16, 8, 64, +                       EVP_CIPH_VARIABLE_LENGTH, bf_init_key, NULL, +                       EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int bf_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                       const unsigned char *iv, int enc) +{ +    BF_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); +    return 1; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_camellia.c b/openssl-1.1.0h/crypto/evp/e_camellia.c new file mode 100644 index 0000000..2df4a6e --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_camellia.c @@ -0,0 +1,366 @@ +/* + * 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 <openssl/opensslconf.h> +#ifdef OPENSSL_NO_CAMELLIA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include <openssl/evp.h> +# include <openssl/err.h> +# include <string.h> +# include <assert.h> +# include <openssl/camellia.h> +# include "internal/evp_int.h" +# include "modes_lcl.h" + +static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc); + +/* Camellia subkey Structure */ +typedef struct { +    CAMELLIA_KEY ks; +    block128_f block; +    union { +        cbc128_f cbc; +        ctr128_f ctr; +    } stream; +} EVP_CAMELLIA_KEY; + +# define MAXBITCHUNK     ((size_t)1<<(sizeof(size_t)*8-4)) + +/* Attribute operation for Camellia */ +# define data(ctx)       EVP_C_DATA(EVP_CAMELLIA_KEY,ctx) + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ---------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +#  include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +#  define SPARC_CMLL_CAPABLE      (OPENSSL_sparcv9cap_P[1] & CFR_CAMELLIA) + +void cmll_t4_set_key(const unsigned char *key, int bits, CAMELLIA_KEY *ks); +void cmll_t4_encrypt(const unsigned char *in, unsigned char *out, +                     const CAMELLIA_KEY *key); +void cmll_t4_decrypt(const unsigned char *in, unsigned char *out, +                     const CAMELLIA_KEY *key); + +void cmll128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, +                            size_t len, const CAMELLIA_KEY *key, +                            unsigned char *ivec); +void cmll128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, +                            size_t len, const CAMELLIA_KEY *key, +                            unsigned char *ivec); +void cmll256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out, +                            size_t len, const CAMELLIA_KEY *key, +                            unsigned char *ivec); +void cmll256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out, +                            size_t len, const CAMELLIA_KEY *key, +                            unsigned char *ivec); +void cmll128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                              size_t blocks, const CAMELLIA_KEY *key, +                              unsigned char *ivec); +void cmll256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out, +                              size_t blocks, const CAMELLIA_KEY *key, +                              unsigned char *ivec); + +static int cmll_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    int ret, mode, bits; +    EVP_CAMELLIA_KEY *dat = +        (EVP_CAMELLIA_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx); + +    mode = EVP_CIPHER_CTX_mode(ctx); +    bits = EVP_CIPHER_CTX_key_length(ctx) * 8; + +    cmll_t4_set_key(key, bits, &dat->ks); + +    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) +        && !enc) { +        ret = 0; +        dat->block = (block128_f) cmll_t4_decrypt; +        switch (bits) { +        case 128: +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) cmll128_t4_cbc_decrypt : NULL; +            break; +        case 192: +        case 256: +            dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +                (cbc128_f) cmll256_t4_cbc_decrypt : NULL; +            break; +        default: +            ret = -1; +        } +    } else { +        ret = 0; +        dat->block = (block128_f) cmll_t4_encrypt; +        switch (bits) { +        case 128: +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) cmll128_t4_cbc_encrypt; +            else if (mode == EVP_CIPH_CTR_MODE) +                dat->stream.ctr = (ctr128_f) cmll128_t4_ctr32_encrypt; +            else +                dat->stream.cbc = NULL; +            break; +        case 192: +        case 256: +            if (mode == EVP_CIPH_CBC_MODE) +                dat->stream.cbc = (cbc128_f) cmll256_t4_cbc_encrypt; +            else if (mode == EVP_CIPH_CTR_MODE) +                dat->stream.ctr = (ctr128_f) cmll256_t4_ctr32_encrypt; +            else +                dat->stream.cbc = NULL; +            break; +        default: +            ret = -1; +        } +    } + +    if (ret < 0) { +        EVPerr(EVP_F_CMLL_T4_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); +        return 0; +    } + +    return 1; +} + +#  define cmll_t4_cbc_cipher camellia_cbc_cipher +static int cmll_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +#  define cmll_t4_ecb_cipher camellia_ecb_cipher +static int cmll_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +#  define cmll_t4_ofb_cipher camellia_ofb_cipher +static int cmll_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +#  define cmll_t4_cfb_cipher camellia_cfb_cipher +static int cmll_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +#  define cmll_t4_cfb8_cipher camellia_cfb8_cipher +static int cmll_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len); + +#  define cmll_t4_cfb1_cipher camellia_cfb1_cipher +static int cmll_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len); + +#  define cmll_t4_ctr_cipher camellia_ctr_cipher +static int cmll_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t len); + +#  define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER cmll_t4_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        cmll_t4_init_key,               \ +        cmll_t4_##mode##_cipher,        \ +        NULL,                           \ +        sizeof(EVP_CAMELLIA_KEY),       \ +        NULL,NULL,NULL,NULL }; \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,     \ +        keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        camellia_init_key,              \ +        camellia_##mode##_cipher,       \ +        NULL,                           \ +        sizeof(EVP_CAMELLIA_KEY),       \ +        NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return SPARC_CMLL_CAPABLE?&cmll_t4_##keylen##_##mode:&camellia_##keylen##_##mode; } + +# else + +#  define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ +static const EVP_CIPHER camellia_##keylen##_##mode = { \ +        nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \ +        flags|EVP_CIPH_##MODE##_MODE,   \ +        camellia_init_key,              \ +        camellia_##mode##_cipher,       \ +        NULL,                           \ +        sizeof(EVP_CAMELLIA_KEY),       \ +        NULL,NULL,NULL,NULL }; \ +const EVP_CIPHER *EVP_camellia_##keylen##_##mode(void) \ +{ return &camellia_##keylen##_##mode; } + +# endif + +# define BLOCK_CIPHER_generic_pack(nid,keylen,flags)             \ +        BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)     \ +        BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)      \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1)   \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags)       \ +        BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags)       \ +        BLOCK_CIPHER_generic(nid, keylen, 1, 16, ctr, ctr, CTR, flags) + +/* The subkey for Camellia is generated. */ +static int camellia_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc) +{ +    int ret, mode; +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    ret = Camellia_set_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, &dat->ks); +    if (ret < 0) { +        EVPerr(EVP_F_CAMELLIA_INIT_KEY, EVP_R_CAMELLIA_KEY_SETUP_FAILED); +        return 0; +    } + +    mode = EVP_CIPHER_CTX_mode(ctx); +    if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) +        && !enc) { +        dat->block = (block128_f) Camellia_decrypt; +        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +            (cbc128_f) Camellia_cbc_encrypt : NULL; +    } else { +        dat->block = (block128_f) Camellia_encrypt; +        dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? +            (cbc128_f) Camellia_cbc_encrypt : NULL; +    } + +    return 1; +} + +static int camellia_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    if (dat->stream.cbc) +        (*dat->stream.cbc) (in, out, len, &dat->ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx), +                            EVP_CIPHER_CTX_encrypting(ctx)); +    else if (EVP_CIPHER_CTX_encrypting(ctx)) +        CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); +    else +        CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), dat->block); + +    return 1; +} + +static int camellia_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    size_t bl = EVP_CIPHER_CTX_block_size(ctx); +    size_t i; +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    if (len < bl) +        return 1; + +    for (i = 0, len -= bl; i <= len; i += bl) +        (*dat->block) (in + i, out + i, &dat->ks); + +    return 1; +} + +static int camellia_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, +                          EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int camellia_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_cfb128_encrypt(in, out, len, &dat->ks, +                          EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int camellia_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t len) +{ +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    int num = EVP_CIPHER_CTX_num(ctx); +    CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +static int camellia_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t len) +{ +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +        return 1; +    } + +    while (len >= MAXBITCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +        len -= MAXBITCHUNK; +        out += MAXBITCHUNK; +        in  += MAXBITCHUNK; +    } +    if (len) { +        int num = EVP_CIPHER_CTX_num(ctx); +        CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks, +                                EVP_CIPHER_CTX_iv_noconst(ctx), &num, EVP_CIPHER_CTX_encrypting(ctx), dat->block); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } + +    return 1; +} + +static int camellia_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    unsigned int num = EVP_CIPHER_CTX_num(ctx); +    EVP_CAMELLIA_KEY *dat = EVP_C_DATA(EVP_CAMELLIA_KEY,ctx); + +    if (dat->stream.ctr) +        CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, +                                    EVP_CIPHER_CTX_iv_noconst(ctx), +                                    EVP_CIPHER_CTX_buf_noconst(ctx), &num, +                                    dat->stream.ctr); +    else +        CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, +                              EVP_CIPHER_CTX_iv_noconst(ctx), +                              EVP_CIPHER_CTX_buf_noconst(ctx), &num, +                              dat->block); +    EVP_CIPHER_CTX_set_num(ctx, num); +    return 1; +} + +BLOCK_CIPHER_generic_pack(NID_camellia, 128, 0) +    BLOCK_CIPHER_generic_pack(NID_camellia, 192, 0) +    BLOCK_CIPHER_generic_pack(NID_camellia, 256, 0) +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_cast.c b/openssl-1.1.0h/crypto/evp/e_cast.c new file mode 100644 index 0000000..259d440 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_cast.c @@ -0,0 +1,40 @@ +/* + * 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" + +#ifndef OPENSSL_NO_CAST +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/cast.h> + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc); + +typedef struct { +    CAST_KEY ks; +} EVP_CAST_KEY; + +# define data(ctx)       EVP_C_DATA(EVP_CAST_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(cast5, ks, CAST, EVP_CAST_KEY, +                       NID_cast5, 8, CAST_KEY_LENGTH, 8, 64, +                       EVP_CIPH_VARIABLE_LENGTH, cast_init_key, NULL, +                       EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int cast_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc) +{ +    CAST_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); +    return 1; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_chacha20_poly1305.c b/openssl-1.1.0h/crypto/evp/e_chacha20_poly1305.c new file mode 100644 index 0000000..7fd4f8d --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_chacha20_poly1305.c @@ -0,0 +1,454 @@ +/* + * 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" + +#ifndef OPENSSL_NO_CHACHA + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "evp_locl.h" +# include "internal/evp_int.h" +# include "internal/chacha.h" + +typedef struct { +    union { +        double align;   /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */ +        unsigned int d[CHACHA_KEY_SIZE / 4]; +    } key; +    unsigned int  counter[CHACHA_CTR_SIZE / 4]; +    unsigned char buf[CHACHA_BLK_SIZE]; +    unsigned int  partial_len; +} EVP_CHACHA_KEY; + +#define data(ctx)   ((EVP_CHACHA_KEY *)(ctx)->cipher_data) + +static int chacha_init_key(EVP_CIPHER_CTX *ctx, +                           const unsigned char user_key[CHACHA_KEY_SIZE], +                           const unsigned char iv[CHACHA_CTR_SIZE], int enc) +{ +    EVP_CHACHA_KEY *key = data(ctx); +    unsigned int i; + +    if (user_key) +        for (i = 0; i < CHACHA_KEY_SIZE; i+=4) { +            key->key.d[i/4] = CHACHA_U8TOU32(user_key+i); +        } + +    if (iv) +        for (i = 0; i < CHACHA_CTR_SIZE; i+=4) { +            key->counter[i/4] = CHACHA_U8TOU32(iv+i); +        } + +    key->partial_len = 0; + +    return 1; +} + +static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out, +                         const unsigned char *inp, size_t len) +{ +    EVP_CHACHA_KEY *key = data(ctx); +    unsigned int n, rem, ctr32; + +    if ((n = key->partial_len)) { +        while (len && n < CHACHA_BLK_SIZE) { +            *out++ = *inp++ ^ key->buf[n++]; +            len--; +        } +        key->partial_len = n; + +        if (len == 0) +            return 1; + +        if (n == CHACHA_BLK_SIZE) { +            key->partial_len = 0; +            key->counter[0]++; +            if (key->counter[0] == 0) +                key->counter[1]++; +        } +    } + +    rem = (unsigned int)(len % CHACHA_BLK_SIZE); +    len -= rem; +    ctr32 = key->counter[0]; +    while (len >= CHACHA_BLK_SIZE) { +        size_t blocks = len / CHACHA_BLK_SIZE; +        /* +         * 1<<28 is just a not-so-small yet not-so-large number... +         * Below condition is practically never met, but it has to +         * be checked for code correctness. +         */ +        if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28)) +            blocks = (1U<<28); + +        /* +         * As ChaCha20_ctr32 operates on 32-bit counter, caller +         * has to handle overflow. 'if' below detects the +         * overflow, which is then handled by limiting the +         * amount of blocks to the exact overflow point... +         */ +        ctr32 += (unsigned int)blocks; +        if (ctr32 < blocks) { +            blocks -= ctr32; +            ctr32 = 0; +        } +        blocks *= CHACHA_BLK_SIZE; +        ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter); +        len -= blocks; +        inp += blocks; +        out += blocks; + +        key->counter[0] = ctr32; +        if (ctr32 == 0) key->counter[1]++; +    } + +    if (rem) { +        memset(key->buf, 0, sizeof(key->buf)); +        ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE, +                       key->key.d, key->counter); +        for (n = 0; n < rem; n++) +            out[n] = inp[n] ^ key->buf[n]; +        key->partial_len = rem; +    } + +    return 1; +} + +static const EVP_CIPHER chacha20 = { +    NID_chacha20, +    1,                      /* block_size */ +    CHACHA_KEY_SIZE,        /* key_len */ +    CHACHA_CTR_SIZE,        /* iv_len, 128-bit counter in the context */ +    EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT, +    chacha_init_key, +    chacha_cipher, +    NULL, +    sizeof(EVP_CHACHA_KEY), +    NULL, +    NULL, +    NULL, +    NULL +}; + +const EVP_CIPHER *EVP_chacha20(void) +{ +    return (&chacha20); +} + +# ifndef OPENSSL_NO_POLY1305 +#  include "internal/poly1305.h" + +typedef struct { +    EVP_CHACHA_KEY key; +    unsigned int nonce[12/4]; +    unsigned char tag[POLY1305_BLOCK_SIZE]; +    struct { uint64_t aad, text; } len; +    int aad, mac_inited, tag_len, nonce_len; +    size_t tls_payload_length; +} EVP_CHACHA_AEAD_CTX; + +#  define NO_TLS_PAYLOAD_LENGTH ((size_t)-1) +#  define aead_data(ctx)        ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data) +#  define POLY1305_ctx(actx)    ((POLY1305 *)(actx + 1)) + +static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx, +                                      const unsigned char *inkey, +                                      const unsigned char *iv, int enc) +{ +    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + +    if (!inkey && !iv) +        return 1; + +    actx->len.aad = 0; +    actx->len.text = 0; +    actx->aad = 0; +    actx->mac_inited = 0; +    actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; + +    if (iv != NULL) { +        unsigned char temp[CHACHA_CTR_SIZE] = { 0 }; + +        /* pad on the left */ +        if (actx->nonce_len <= CHACHA_CTR_SIZE) +            memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv, actx->nonce_len); + +        chacha_init_key(ctx, inkey, temp, enc); + +        actx->nonce[0] = actx->key.counter[1]; +        actx->nonce[1] = actx->key.counter[2]; +        actx->nonce[2] = actx->key.counter[3]; +    } else { +        chacha_init_key(ctx, inkey, NULL, enc); +    } + +    return 1; +} + +static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                    const unsigned char *in, size_t len) +{ +    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); +    size_t rem, plen = actx->tls_payload_length; +    static const unsigned char zero[POLY1305_BLOCK_SIZE] = { 0 }; + +    if (!actx->mac_inited) { +        actx->key.counter[0] = 0; +        memset(actx->key.buf, 0, sizeof(actx->key.buf)); +        ChaCha20_ctr32(actx->key.buf, actx->key.buf, CHACHA_BLK_SIZE, +                       actx->key.key.d, actx->key.counter); +        Poly1305_Init(POLY1305_ctx(actx), actx->key.buf); +        actx->key.counter[0] = 1; +        actx->key.partial_len = 0; +        actx->len.aad = actx->len.text = 0; +        actx->mac_inited = 1; +    } + +    if (in) {                                   /* aad or text */ +        if (out == NULL) {                      /* aad */ +            Poly1305_Update(POLY1305_ctx(actx), in, len); +            actx->len.aad += len; +            actx->aad = 1; +            return len; +        } else {                                /* plain- or ciphertext */ +            if (actx->aad) {                    /* wrap up aad */ +                if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) +                    Poly1305_Update(POLY1305_ctx(actx), zero, +                                    POLY1305_BLOCK_SIZE - rem); +                actx->aad = 0; +            } + +            actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; +            if (plen == NO_TLS_PAYLOAD_LENGTH) +                plen = len; +            else if (len != plen + POLY1305_BLOCK_SIZE) +                return -1; + +            if (ctx->encrypt) {                 /* plaintext */ +                chacha_cipher(ctx, out, in, plen); +                Poly1305_Update(POLY1305_ctx(actx), out, plen); +                in += plen; +                out += plen; +                actx->len.text += plen; +            } else {                            /* ciphertext */ +                Poly1305_Update(POLY1305_ctx(actx), in, plen); +                chacha_cipher(ctx, out, in, plen); +                in += plen; +                out += plen; +                actx->len.text += plen; +            } +        } +    } +    if (in == NULL                              /* explicit final */ +        || plen != len) {                       /* or tls mode */ +        const union { +            long one; +            char little; +        } is_endian = { 1 }; +        unsigned char temp[POLY1305_BLOCK_SIZE]; + +        if (actx->aad) {                        /* wrap up aad */ +            if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE)) +                Poly1305_Update(POLY1305_ctx(actx), zero, +                                POLY1305_BLOCK_SIZE - rem); +            actx->aad = 0; +        } + +        if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE)) +            Poly1305_Update(POLY1305_ctx(actx), zero, +                            POLY1305_BLOCK_SIZE - rem); + +        if (is_endian.little) { +            Poly1305_Update(POLY1305_ctx(actx), +                            (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE); +        } else { +            temp[0]  = (unsigned char)(actx->len.aad); +            temp[1]  = (unsigned char)(actx->len.aad>>8); +            temp[2]  = (unsigned char)(actx->len.aad>>16); +            temp[3]  = (unsigned char)(actx->len.aad>>24); +            temp[4]  = (unsigned char)(actx->len.aad>>32); +            temp[5]  = (unsigned char)(actx->len.aad>>40); +            temp[6]  = (unsigned char)(actx->len.aad>>48); +            temp[7]  = (unsigned char)(actx->len.aad>>56); + +            temp[8]  = (unsigned char)(actx->len.text); +            temp[9]  = (unsigned char)(actx->len.text>>8); +            temp[10] = (unsigned char)(actx->len.text>>16); +            temp[11] = (unsigned char)(actx->len.text>>24); +            temp[12] = (unsigned char)(actx->len.text>>32); +            temp[13] = (unsigned char)(actx->len.text>>40); +            temp[14] = (unsigned char)(actx->len.text>>48); +            temp[15] = (unsigned char)(actx->len.text>>56); + +            Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE); +        } +        Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag +                                                        : temp); +        actx->mac_inited = 0; + +        if (in != NULL && len != plen) {        /* tls mode */ +            if (ctx->encrypt) { +                memcpy(out, actx->tag, POLY1305_BLOCK_SIZE); +            } else { +                if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) { +                    memset(out - plen, 0, plen); +                    return -1; +                } +            } +        } +        else if (!ctx->encrypt) { +            if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len)) +                return -1; +        } +    } +    return len; +} + +static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx) +{ +    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); +    if (actx) +        OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size()); +    return 1; +} + +static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, +                                  void *ptr) +{ +    EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx); + +    switch(type) { +    case EVP_CTRL_INIT: +        if (actx == NULL) +            actx = ctx->cipher_data +                 = OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size()); +        if (actx == NULL) { +            EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR); +            return 0; +        } +        actx->len.aad = 0; +        actx->len.text = 0; +        actx->aad = 0; +        actx->mac_inited = 0; +        actx->tag_len = 0; +        actx->nonce_len = 12; +        actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH; +        return 1; + +    case EVP_CTRL_COPY: +        if (actx) { +            EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr; + +            dst->cipher_data = +                   OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size()); +            if (dst->cipher_data == NULL) { +                EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR); +                return 0; +            } +        } +        return 1; + +    case EVP_CTRL_AEAD_SET_IVLEN: +        if (arg <= 0 || arg > CHACHA_CTR_SIZE) +            return 0; +        actx->nonce_len = arg; +        return 1; + +    case EVP_CTRL_AEAD_SET_IV_FIXED: +        if (arg != 12) +            return 0; +        actx->nonce[0] = actx->key.counter[1] +                       = CHACHA_U8TOU32((unsigned char *)ptr); +        actx->nonce[1] = actx->key.counter[2] +                       = CHACHA_U8TOU32((unsigned char *)ptr+4); +        actx->nonce[2] = actx->key.counter[3] +                       = CHACHA_U8TOU32((unsigned char *)ptr+8); +        return 1; + +    case EVP_CTRL_AEAD_SET_TAG: +        if (arg <= 0 || arg > POLY1305_BLOCK_SIZE) +            return 0; +        if (ptr != NULL) { +            memcpy(actx->tag, ptr, arg); +            actx->tag_len = arg; +        } +        return 1; + +    case EVP_CTRL_AEAD_GET_TAG: +        if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt) +            return 0; +        memcpy(ptr, actx->tag, arg); +        return 1; + +    case EVP_CTRL_AEAD_TLS1_AAD: +        if (arg != EVP_AEAD_TLS1_AAD_LEN) +            return 0; +        { +            unsigned int len; +            unsigned char *aad = ptr, temp[POLY1305_BLOCK_SIZE]; + +            len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 | +                  aad[EVP_AEAD_TLS1_AAD_LEN - 1]; +            if (!ctx->encrypt) { +                if (len < POLY1305_BLOCK_SIZE) +                    return 0; +                len -= POLY1305_BLOCK_SIZE;     /* discount attached tag */ +                memcpy(temp, aad, EVP_AEAD_TLS1_AAD_LEN - 2); +                aad = temp; +                temp[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8); +                temp[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len; +            } +            actx->tls_payload_length = len; + +            /* +             * merge record sequence number as per RFC7905 +             */ +            actx->key.counter[1] = actx->nonce[0]; +            actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad); +            actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4); +            actx->mac_inited = 0; +            chacha20_poly1305_cipher(ctx, NULL, aad, EVP_AEAD_TLS1_AAD_LEN); +            return POLY1305_BLOCK_SIZE;         /* tag length */ +        } + +    case EVP_CTRL_AEAD_SET_MAC_KEY: +        /* no-op */ +        return 1; + +    default: +        return -1; +    } +} + +static EVP_CIPHER chacha20_poly1305 = { +    NID_chacha20_poly1305, +    1,                  /* block_size */ +    CHACHA_KEY_SIZE,    /* key_len */ +    12,                 /* iv_len, 96-bit nonce in the context */ +    EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV | +    EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | +    EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER, +    chacha20_poly1305_init_key, +    chacha20_poly1305_cipher, +    chacha20_poly1305_cleanup, +    0,          /* 0 moves context-specific structure allocation to ctrl */ +    NULL,       /* set_asn1_parameters */ +    NULL,       /* get_asn1_parameters */ +    chacha20_poly1305_ctrl, +    NULL        /* app_data */ +}; + +const EVP_CIPHER *EVP_chacha20_poly1305(void) +{ +    return(&chacha20_poly1305); +} +# endif +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_des.c b/openssl-1.1.0h/crypto/evp/e_des.c new file mode 100644 index 0000000..9b2facf --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_des.c @@ -0,0 +1,242 @@ +/* + * 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" +#ifndef OPENSSL_NO_DES +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/des.h> +# include <openssl/rand.h> + +typedef struct { +    union { +        double align; +        DES_key_schedule ks; +    } ks; +    union { +        void (*cbc) (const void *, void *, size_t, +                     const DES_key_schedule *, unsigned char *); +    } stream; +} EVP_DES_KEY; + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ----------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +#  include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +#  define SPARC_DES_CAPABLE       (OPENSSL_sparcv9cap_P[1] & CFR_DES) + +void des_t4_key_expand(const void *key, DES_key_schedule *ks); +void des_t4_cbc_encrypt(const void *inp, void *out, size_t len, +                        const DES_key_schedule *ks, unsigned char iv[8]); +void des_t4_cbc_decrypt(const void *inp, void *out, size_t len, +                        const DES_key_schedule *ks, unsigned char iv[8]); +# endif + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc); +static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +/* + * Because of various casts and different names can't use + * IMPLEMENT_BLOCK_CIPHER + */ + +static int des_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t inl) +{ +    BLOCK_CIPHER_ecb_loop() +        DES_ecb_encrypt((DES_cblock *)(in + i), (DES_cblock *)(out + i), +                        EVP_CIPHER_CTX_get_cipher_data(ctx), +                        EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +static int des_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, +                          EVP_CIPHER_CTX_get_cipher_data(ctx), +                          (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num); +        EVP_CIPHER_CTX_set_num(ctx, num); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ofb64_encrypt(in, out, (long)inl, +                          EVP_CIPHER_CTX_get_cipher_data(ctx), +                          (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } +    return 1; +} + +static int des_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                          const unsigned char *in, size_t inl) +{ +    EVP_DES_KEY *dat = (EVP_DES_KEY *) EVP_CIPHER_CTX_get_cipher_data(ctx); + +    if (dat->stream.cbc != NULL) { +        (*dat->stream.cbc) (in, out, inl, &dat->ks.ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx)); +        return 1; +    } +    while (inl >= EVP_MAXCHUNK) { +        DES_ncbc_encrypt(in, out, (long)EVP_MAXCHUNK, +                         EVP_CIPHER_CTX_get_cipher_data(ctx), +                         (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                         EVP_CIPHER_CTX_encrypting(ctx)); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) +        DES_ncbc_encrypt(in, out, (long)inl, +                         EVP_CIPHER_CTX_get_cipher_data(ctx), +                         (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                         EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +static int des_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                            const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK, +                          EVP_CIPHER_CTX_get_cipher_data(ctx), +                          (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                          EVP_CIPHER_CTX_encrypting(ctx)); +        EVP_CIPHER_CTX_set_num(ctx, num); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_cfb64_encrypt(in, out, (long)inl, +                          EVP_CIPHER_CTX_get_cipher_data(ctx), +                          (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), &num, +                          EVP_CIPHER_CTX_encrypting(ctx)); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } +    return 1; +} + +/* + * Although we have a CFB-r implementation for DES, it doesn't pack the right + * way, so wrap it here + */ +static int des_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl) +{ +    size_t n, chunk = EVP_MAXCHUNK / 8; +    unsigned char c[1], d[1]; + +    if (inl < chunk) +        chunk = inl; + +    while (inl && inl >= chunk) { +        for (n = 0; n < chunk * 8; ++n) { +            c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; +            DES_cfb_encrypt(c, d, 1, 1, EVP_CIPHER_CTX_get_cipher_data(ctx), +                            (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                            EVP_CIPHER_CTX_encrypting(ctx)); +            out[n / 8] = +                (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) | +                ((d[0] & 0x80) >> (unsigned int)(n % 8)); +        } +        inl -= chunk; +        in += chunk; +        out += chunk; +        if (inl < chunk) +            chunk = inl; +    } + +    return 1; +} + +static int des_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        DES_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK, +                        EVP_CIPHER_CTX_get_cipher_data(ctx), +                        (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                        EVP_CIPHER_CTX_encrypting(ctx)); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) +        DES_cfb_encrypt(in, out, 8, (long)inl, +                        EVP_CIPHER_CTX_get_cipher_data(ctx), +                        (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                        EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +BLOCK_CIPHER_defs(des, EVP_DES_KEY, NID_des, 8, 8, 8, 64, +                  EVP_CIPH_RAND_KEY, des_init_key, NULL, +                  EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + +    BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 1, +                     EVP_CIPH_RAND_KEY, des_init_key, NULL, +                     EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + +    BLOCK_CIPHER_def_cfb(des, EVP_DES_KEY, NID_des, 8, 8, 8, +                     EVP_CIPH_RAND_KEY, des_init_key, NULL, +                     EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, des_ctrl) + +static int des_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc) +{ +    DES_cblock *deskey = (DES_cblock *)key; +    EVP_DES_KEY *dat = (EVP_DES_KEY *) EVP_CIPHER_CTX_get_cipher_data(ctx); + +    dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) +    if (SPARC_DES_CAPABLE) { +        int mode = EVP_CIPHER_CTX_mode(ctx); + +        if (mode == EVP_CIPH_CBC_MODE) { +            des_t4_key_expand(key, &dat->ks.ks); +            dat->stream.cbc = enc ? des_t4_cbc_encrypt : des_t4_cbc_decrypt; +            return 1; +        } +    } +# endif +    DES_set_key_unchecked(deskey, EVP_CIPHER_CTX_get_cipher_data(ctx)); +    return 1; +} + +static int des_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + +    switch (type) { +    case EVP_CTRL_RAND_KEY: +        if (RAND_bytes(ptr, 8) <= 0) +            return 0; +        DES_set_odd_parity((DES_cblock *)ptr); +        return 1; + +    default: +        return -1; +    } +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_des3.c b/openssl-1.1.0h/crypto/evp/e_des3.c new file mode 100644 index 0000000..da77936 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_des3.c @@ -0,0 +1,424 @@ +/* + * 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" +#ifndef OPENSSL_NO_DES +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/des.h> +# include <openssl/rand.h> +# include "evp_locl.h" + +typedef struct { +    union { +        double align; +        DES_key_schedule ks[3]; +    } ks; +    union { +        void (*cbc) (const void *, void *, size_t, +                     const DES_key_schedule *, unsigned char *); +    } stream; +} DES_EDE_KEY; +# define ks1 ks.ks[0] +# define ks2 ks.ks[1] +# define ks3 ks.ks[2] + +# if defined(AES_ASM) && (defined(__sparc) || defined(__sparc__)) +/* ---------^^^ this is not a typo, just a way to detect that + * assembler support was in general requested... */ +#  include "sparc_arch.h" + +extern unsigned int OPENSSL_sparcv9cap_P[]; + +#  define SPARC_DES_CAPABLE       (OPENSSL_sparcv9cap_P[1] & CFR_DES) + +void des_t4_key_expand(const void *key, DES_key_schedule *ks); +void des_t4_ede3_cbc_encrypt(const void *inp, void *out, size_t len, +                             const DES_key_schedule ks[3], unsigned char iv[8]); +void des_t4_ede3_cbc_decrypt(const void *inp, void *out, size_t len, +                             const DES_key_schedule ks[3], unsigned char iv[8]); +# endif + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc); + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc); + +static int des3_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +# define data(ctx) EVP_C_DATA(DES_EDE_KEY,ctx) + +/* + * Because of various casts and different args can't use + * IMPLEMENT_BLOCK_CIPHER + */ + +static int des_ede_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t inl) +{ +    BLOCK_CIPHER_ecb_loop() +        DES_ecb3_encrypt((const_DES_cblock *)(in + i), +                         (DES_cblock *)(out + i), +                         &data(ctx)->ks1, &data(ctx)->ks2, +                         &data(ctx)->ks3, EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +static int des_ede_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ede3_ofb64_encrypt(in, out, (long)EVP_MAXCHUNK, +                               &data(ctx)->ks1, &data(ctx)->ks2, +                               &data(ctx)->ks3, +                               (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                               &num); +        EVP_CIPHER_CTX_set_num(ctx, num); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ede3_ofb64_encrypt(in, out, (long)inl, +                               &data(ctx)->ks1, &data(ctx)->ks2, +                               &data(ctx)->ks3, +                               (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                               &num); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } +    return 1; +} + +static int des_ede_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                              const unsigned char *in, size_t inl) +{ +    DES_EDE_KEY *dat = data(ctx); + +    if (dat->stream.cbc != NULL) { +        (*dat->stream.cbc) (in, out, inl, dat->ks.ks, +                            EVP_CIPHER_CTX_iv_noconst(ctx)); +        return 1; +    } + +    while (inl >= EVP_MAXCHUNK) { +        DES_ede3_cbc_encrypt(in, out, (long)EVP_MAXCHUNK, +                             &dat->ks1, &dat->ks2, &dat->ks3, +                             (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                             EVP_CIPHER_CTX_encrypting(ctx)); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) +        DES_ede3_cbc_encrypt(in, out, (long)inl, +                             &dat->ks1, &dat->ks2, &dat->ks3, +                             (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                             EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +static int des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ede3_cfb64_encrypt(in, out, (long)EVP_MAXCHUNK, +                               &data(ctx)->ks1, &data(ctx)->ks2, +                               &data(ctx)->ks3, +                               (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                               &num, EVP_CIPHER_CTX_encrypting(ctx)); +        EVP_CIPHER_CTX_set_num(ctx, num); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) { +        int num = EVP_CIPHER_CTX_num(ctx); +        DES_ede3_cfb64_encrypt(in, out, (long)inl, +                               &data(ctx)->ks1, &data(ctx)->ks2, +                               &data(ctx)->ks3, +                               (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                               &num, EVP_CIPHER_CTX_encrypting(ctx)); +        EVP_CIPHER_CTX_set_num(ctx, num); +    } +    return 1; +} + +/* + * Although we have a CFB-r implementation for 3-DES, it doesn't pack the + * right way, so wrap it here + */ +static int des_ede3_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t inl) +{ +    size_t n; +    unsigned char c[1], d[1]; + +    if (!EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) +            inl *= 8; +    for (n = 0; n < inl; ++n) { +        c[0] = (in[n / 8] & (1 << (7 - n % 8))) ? 0x80 : 0; +        DES_ede3_cfb_encrypt(c, d, 1, 1, +                             &data(ctx)->ks1, &data(ctx)->ks2, +                             &data(ctx)->ks3, +                             (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                             EVP_CIPHER_CTX_encrypting(ctx)); +        out[n / 8] = (out[n / 8] & ~(0x80 >> (unsigned int)(n % 8))) +            | ((d[0] & 0x80) >> (unsigned int)(n % 8)); +    } + +    return 1; +} + +static int des_ede3_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        DES_ede3_cfb_encrypt(in, out, 8, (long)EVP_MAXCHUNK, +                             &data(ctx)->ks1, &data(ctx)->ks2, +                             &data(ctx)->ks3, +                             (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                             EVP_CIPHER_CTX_encrypting(ctx)); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) +        DES_ede3_cfb_encrypt(in, out, 8, (long)inl, +                             &data(ctx)->ks1, &data(ctx)->ks2, +                             &data(ctx)->ks3, +                             (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                             EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} + +BLOCK_CIPHER_defs(des_ede, DES_EDE_KEY, NID_des_ede, 8, 16, 8, 64, +                  EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, +                  des_ede_init_key, NULL, NULL, NULL, des3_ctrl) +# define des_ede3_cfb64_cipher des_ede_cfb64_cipher +# define des_ede3_ofb_cipher des_ede_ofb_cipher +# define des_ede3_cbc_cipher des_ede_cbc_cipher +# define des_ede3_ecb_cipher des_ede_ecb_cipher +    BLOCK_CIPHER_defs(des_ede3, DES_EDE_KEY, NID_des_ede3, 8, 24, 8, 64, +                  EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, +                  des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + +    BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 1, +                     EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, +                     des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + +    BLOCK_CIPHER_def_cfb(des_ede3, DES_EDE_KEY, NID_des_ede3, 24, 8, 8, +                     EVP_CIPH_RAND_KEY | EVP_CIPH_FLAG_DEFAULT_ASN1, +                     des_ede3_init_key, NULL, NULL, NULL, des3_ctrl) + +static int des_ede_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                            const unsigned char *iv, int enc) +{ +    DES_cblock *deskey = (DES_cblock *)key; +    DES_EDE_KEY *dat = data(ctx); + +    dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) +    if (SPARC_DES_CAPABLE) { +        int mode = EVP_CIPHER_CTX_mode(ctx); + +        if (mode == EVP_CIPH_CBC_MODE) { +            des_t4_key_expand(&deskey[0], &dat->ks1); +            des_t4_key_expand(&deskey[1], &dat->ks2); +            memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1)); +            dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt : +                des_t4_ede3_cbc_decrypt; +            return 1; +        } +    } +# endif +    DES_set_key_unchecked(&deskey[0], &dat->ks1); +    DES_set_key_unchecked(&deskey[1], &dat->ks2); +    memcpy(&dat->ks3, &dat->ks1, sizeof(dat->ks1)); +    return 1; +} + +static int des_ede3_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc) +{ +    DES_cblock *deskey = (DES_cblock *)key; +    DES_EDE_KEY *dat = data(ctx); + +    dat->stream.cbc = NULL; +# if defined(SPARC_DES_CAPABLE) +    if (SPARC_DES_CAPABLE) { +        int mode = EVP_CIPHER_CTX_mode(ctx); + +        if (mode == EVP_CIPH_CBC_MODE) { +            des_t4_key_expand(&deskey[0], &dat->ks1); +            des_t4_key_expand(&deskey[1], &dat->ks2); +            des_t4_key_expand(&deskey[2], &dat->ks3); +            dat->stream.cbc = enc ? des_t4_ede3_cbc_encrypt : +                des_t4_ede3_cbc_decrypt; +            return 1; +        } +    } +# endif +    DES_set_key_unchecked(&deskey[0], &dat->ks1); +    DES_set_key_unchecked(&deskey[1], &dat->ks2); +    DES_set_key_unchecked(&deskey[2], &dat->ks3); +    return 1; +} + +static int des3_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ + +    DES_cblock *deskey = ptr; + +    switch (type) { +    case EVP_CTRL_RAND_KEY: +        if (RAND_bytes(ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) +            return 0; +        DES_set_odd_parity(deskey); +        if (EVP_CIPHER_CTX_key_length(ctx) >= 16) +            DES_set_odd_parity(deskey + 1); +        if (EVP_CIPHER_CTX_key_length(ctx) >= 24) +            DES_set_odd_parity(deskey + 2); +        return 1; + +    default: +        return -1; +    } +} + +const EVP_CIPHER *EVP_des_ede(void) +{ +    return &des_ede_ecb; +} + +const EVP_CIPHER *EVP_des_ede3(void) +{ +    return &des_ede3_ecb; +} + + +# include <openssl/sha.h> + +static const unsigned char wrap_iv[8] = +    { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; + +static int des_ede3_unwrap(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl) +{ +    unsigned char icv[8], iv[8], sha1tmp[SHA_DIGEST_LENGTH]; +    int rv = -1; +    if (inl < 24) +        return -1; +    if (out == NULL) +        return inl - 16; +    memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8); +    /* Decrypt first block which will end up as icv */ +    des_ede_cbc_cipher(ctx, icv, in, 8); +    /* Decrypt central blocks */ +    /* +     * If decrypting in place move whole output along a block so the next +     * des_ede_cbc_cipher is in place. +     */ +    if (out == in) { +        memmove(out, out + 8, inl - 8); +        in -= 8; +    } +    des_ede_cbc_cipher(ctx, out, in + 8, inl - 16); +    /* Decrypt final block which will be IV */ +    des_ede_cbc_cipher(ctx, iv, in + inl - 8, 8); +    /* Reverse order of everything */ +    BUF_reverse(icv, NULL, 8); +    BUF_reverse(out, NULL, inl - 16); +    BUF_reverse(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 8); +    /* Decrypt again using new IV */ +    des_ede_cbc_cipher(ctx, out, out, inl - 16); +    des_ede_cbc_cipher(ctx, icv, icv, 8); +    /* Work out SHA1 hash of first portion */ +    SHA1(out, inl - 16, sha1tmp); + +    if (!CRYPTO_memcmp(sha1tmp, icv, 8)) +        rv = inl - 16; +    OPENSSL_cleanse(icv, 8); +    OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); +    OPENSSL_cleanse(iv, 8); +    OPENSSL_cleanse(EVP_CIPHER_CTX_iv_noconst(ctx), 8); +    if (rv == -1) +        OPENSSL_cleanse(out, inl - 16); + +    return rv; +} + +static int des_ede3_wrap(EVP_CIPHER_CTX *ctx, unsigned char *out, +                         const unsigned char *in, size_t inl) +{ +    unsigned char sha1tmp[SHA_DIGEST_LENGTH]; +    if (out == NULL) +        return inl + 16; +    /* Copy input to output buffer + 8 so we have space for IV */ +    memmove(out + 8, in, inl); +    /* Work out ICV */ +    SHA1(in, inl, sha1tmp); +    memcpy(out + inl + 8, sha1tmp, 8); +    OPENSSL_cleanse(sha1tmp, SHA_DIGEST_LENGTH); +    /* Generate random IV */ +    if (RAND_bytes(EVP_CIPHER_CTX_iv_noconst(ctx), 8) <= 0) +        return -1; +    memcpy(out, EVP_CIPHER_CTX_iv_noconst(ctx), 8); +    /* Encrypt everything after IV in place */ +    des_ede_cbc_cipher(ctx, out + 8, out + 8, inl + 8); +    BUF_reverse(out, NULL, inl + 16); +    memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), wrap_iv, 8); +    des_ede_cbc_cipher(ctx, out, out, inl + 16); +    return inl + 16; +} + +static int des_ede3_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                                const unsigned char *in, size_t inl) +{ +    /* +     * Sanity check input length: we typically only wrap keys so EVP_MAXCHUNK +     * is more than will ever be needed. Also input length must be a multiple +     * of 8 bits. +     */ +    if (inl >= EVP_MAXCHUNK || inl % 8) +        return -1; + +    if (is_partially_overlapping(out, in, inl)) { +        EVPerr(EVP_F_DES_EDE3_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING); +        return 0; +    } + +    if (EVP_CIPHER_CTX_encrypting(ctx)) +        return des_ede3_wrap(ctx, out, in, inl); +    else +        return des_ede3_unwrap(ctx, out, in, inl); +} + +static const EVP_CIPHER des3_wrap = { +    NID_id_smime_alg_CMS3DESwrap, +    8, 24, 0, +    EVP_CIPH_WRAP_MODE | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER +        | EVP_CIPH_FLAG_DEFAULT_ASN1, +    des_ede3_init_key, des_ede3_wrap_cipher, +    NULL, +    sizeof(DES_EDE_KEY), +    NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_des_ede3_wrap(void) +{ +    return &des3_wrap; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_idea.c b/openssl-1.1.0h/crypto/evp/e_idea.c new file mode 100644 index 0000000..93f6a41 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_idea.c @@ -0,0 +1,70 @@ +/* + * 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" + +#ifndef OPENSSL_NO_IDEA +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/idea.h> + +/* Can't use IMPLEMENT_BLOCK_CIPHER because IDEA_ecb_encrypt is different */ + +typedef struct { +    IDEA_KEY_SCHEDULE ks; +} EVP_IDEA_KEY; + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc); + +/* + * NB IDEA_ecb_encrypt doesn't take an 'encrypt' argument so we treat it as a + * special case + */ + +static int idea_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl) +{ +    BLOCK_CIPHER_ecb_loop() +        IDEA_ecb_encrypt(in + i, out + i, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); +    return 1; +} + +BLOCK_CIPHER_func_cbc(idea, IDEA, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_ofb(idea, IDEA, 64, EVP_IDEA_KEY, ks) +BLOCK_CIPHER_func_cfb(idea, IDEA, 64, EVP_IDEA_KEY, ks) + +BLOCK_CIPHER_defs(idea, IDEA_KEY_SCHEDULE, NID_idea, 8, 16, 8, 64, +                  0, idea_init_key, NULL, +                  EVP_CIPHER_set_asn1_iv, EVP_CIPHER_get_asn1_iv, NULL) + +static int idea_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc) +{ +    if (!enc) { +        if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) +            enc = 1; +        else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) +            enc = 1; +    } +    if (enc) +        IDEA_set_encrypt_key(key, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); +    else { +        IDEA_KEY_SCHEDULE tmp; + +        IDEA_set_encrypt_key(key, &tmp); +        IDEA_set_decrypt_key(&tmp, &EVP_C_DATA(EVP_IDEA_KEY,ctx)->ks); +        OPENSSL_cleanse((unsigned char *)&tmp, sizeof(IDEA_KEY_SCHEDULE)); +    } +    return 1; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_null.c b/openssl-1.1.0h/crypto/evp/e_null.c new file mode 100644 index 0000000..0dfc48a --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_null.c @@ -0,0 +1,50 @@ +/* + * 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 "internal/evp_int.h" + +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc); +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                       const unsigned char *in, size_t inl); +static const EVP_CIPHER n_cipher = { +    NID_undef, +    1, 0, 0, 0, +    null_init_key, +    null_cipher, +    NULL, +    0, +    NULL, +    NULL, +    NULL, +    NULL +}; + +const EVP_CIPHER *EVP_enc_null(void) +{ +    return (&n_cipher); +} + +static int null_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc) +{ +    return 1; +} + +static int null_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                       const unsigned char *in, size_t inl) +{ +    if (in != out) +        memcpy(out, in, inl); +    return 1; +} diff --git a/openssl-1.1.0h/crypto/evp/e_old.c b/openssl-1.1.0h/crypto/evp/e_old.c new file mode 100644 index 0000000..927908f --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_old.c @@ -0,0 +1,113 @@ +/* + * Copyright 2004-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> +#if OPENSSL_API_COMPAT >= 0x00908000L +NON_EMPTY_TRANSLATION_UNIT +#else + +# include <openssl/evp.h> + +/* + * Define some deprecated functions, so older programs don't crash and burn + * too quickly.  On Windows and VMS, these will never be used, since + * functions and variables in shared libraries are selected by entry point + * location, not by name. + */ + +# ifndef OPENSSL_NO_BF +#  undef EVP_bf_cfb +const EVP_CIPHER *EVP_bf_cfb(void); +const EVP_CIPHER *EVP_bf_cfb(void) +{ +    return EVP_bf_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_DES +#  undef EVP_des_cfb +const EVP_CIPHER *EVP_des_cfb(void); +const EVP_CIPHER *EVP_des_cfb(void) +{ +    return EVP_des_cfb64(); +} + +#  undef EVP_des_ede3_cfb +const EVP_CIPHER *EVP_des_ede3_cfb(void); +const EVP_CIPHER *EVP_des_ede3_cfb(void) +{ +    return EVP_des_ede3_cfb64(); +} + +#  undef EVP_des_ede_cfb +const EVP_CIPHER *EVP_des_ede_cfb(void); +const EVP_CIPHER *EVP_des_ede_cfb(void) +{ +    return EVP_des_ede_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_IDEA +#  undef EVP_idea_cfb +const EVP_CIPHER *EVP_idea_cfb(void); +const EVP_CIPHER *EVP_idea_cfb(void) +{ +    return EVP_idea_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_RC2 +#  undef EVP_rc2_cfb +const EVP_CIPHER *EVP_rc2_cfb(void); +const EVP_CIPHER *EVP_rc2_cfb(void) +{ +    return EVP_rc2_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_CAST +#  undef EVP_cast5_cfb +const EVP_CIPHER *EVP_cast5_cfb(void); +const EVP_CIPHER *EVP_cast5_cfb(void) +{ +    return EVP_cast5_cfb64(); +} +# endif + +# ifndef OPENSSL_NO_RC5 +#  undef EVP_rc5_32_12_16_cfb +const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void); +const EVP_CIPHER *EVP_rc5_32_12_16_cfb(void) +{ +    return EVP_rc5_32_12_16_cfb64(); +} +# endif + +# undef EVP_aes_128_cfb +const EVP_CIPHER *EVP_aes_128_cfb(void); +const EVP_CIPHER *EVP_aes_128_cfb(void) +{ +    return EVP_aes_128_cfb128(); +} + +# undef EVP_aes_192_cfb +const EVP_CIPHER *EVP_aes_192_cfb(void); +const EVP_CIPHER *EVP_aes_192_cfb(void) +{ +    return EVP_aes_192_cfb128(); +} + +# undef EVP_aes_256_cfb +const EVP_CIPHER *EVP_aes_256_cfb(void); +const EVP_CIPHER *EVP_aes_256_cfb(void) +{ +    return EVP_aes_256_cfb128(); +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_rc2.c b/openssl-1.1.0h/crypto/evp/e_rc2.c new file mode 100644 index 0000000..ed10bb3 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_rc2.c @@ -0,0 +1,189 @@ +/* + * 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" + +#ifndef OPENSSL_NO_RC2 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/rc2.h> + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc); +static int rc2_meth_to_magic(EVP_CIPHER_CTX *ctx); +static int rc2_magic_to_meth(int i); +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type); +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +typedef struct { +    int key_bits;               /* effective key bits */ +    RC2_KEY ks;                 /* key schedule */ +} EVP_RC2_KEY; + +# define data(ctx)       EVP_C_DATA(EVP_RC2_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(rc2, ks, RC2, EVP_RC2_KEY, NID_rc2, +                       8, +                       RC2_KEY_LENGTH, 8, 64, +                       EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, +                       rc2_init_key, NULL, +                       rc2_set_asn1_type_and_iv, rc2_get_asn1_type_and_iv, +                       rc2_ctrl) +# define RC2_40_MAGIC    0xa0 +# define RC2_64_MAGIC    0x78 +# define RC2_128_MAGIC   0x3a +static const EVP_CIPHER r2_64_cbc_cipher = { +    NID_rc2_64_cbc, +    8, 8 /* 64 bit */ , 8, +    EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, +    rc2_init_key, +    rc2_cbc_cipher, +    NULL, +    sizeof(EVP_RC2_KEY), +    rc2_set_asn1_type_and_iv, +    rc2_get_asn1_type_and_iv, +    rc2_ctrl, +    NULL +}; + +static const EVP_CIPHER r2_40_cbc_cipher = { +    NID_rc2_40_cbc, +    8, 5 /* 40 bit */ , 8, +    EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, +    rc2_init_key, +    rc2_cbc_cipher, +    NULL, +    sizeof(EVP_RC2_KEY), +    rc2_set_asn1_type_and_iv, +    rc2_get_asn1_type_and_iv, +    rc2_ctrl, +    NULL +}; + +const EVP_CIPHER *EVP_rc2_64_cbc(void) +{ +    return (&r2_64_cbc_cipher); +} + +const EVP_CIPHER *EVP_rc2_40_cbc(void) +{ +    return (&r2_40_cbc_cipher); +} + +static int rc2_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc) +{ +    RC2_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), +                key, data(ctx)->key_bits); +    return 1; +} + +static int rc2_meth_to_magic(EVP_CIPHER_CTX *e) +{ +    int i; + +    EVP_CIPHER_CTX_ctrl(e, EVP_CTRL_GET_RC2_KEY_BITS, 0, &i); +    if (i == 128) +        return (RC2_128_MAGIC); +    else if (i == 64) +        return (RC2_64_MAGIC); +    else if (i == 40) +        return (RC2_40_MAGIC); +    else +        return (0); +} + +static int rc2_magic_to_meth(int i) +{ +    if (i == RC2_128_MAGIC) +        return 128; +    else if (i == RC2_64_MAGIC) +        return 64; +    else if (i == RC2_40_MAGIC) +        return 40; +    else { +        EVPerr(EVP_F_RC2_MAGIC_TO_METH, EVP_R_UNSUPPORTED_KEY_SIZE); +        return (0); +    } +} + +static int rc2_get_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    long num = 0; +    int i = 0; +    int key_bits; +    unsigned int l; +    unsigned char iv[EVP_MAX_IV_LENGTH]; + +    if (type != NULL) { +        l = EVP_CIPHER_CTX_iv_length(c); +        OPENSSL_assert(l <= sizeof(iv)); +        i = ASN1_TYPE_get_int_octetstring(type, &num, iv, l); +        if (i != (int)l) +            return -1; +        key_bits = rc2_magic_to_meth((int)num); +        if (!key_bits) +            return -1; +        if (i > 0 && !EVP_CipherInit_ex(c, NULL, NULL, NULL, iv, -1)) +            return -1; +        EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_RC2_KEY_BITS, key_bits, NULL); +        if (EVP_CIPHER_CTX_set_key_length(c, key_bits / 8) <= 0) +            return -1; +    } +    return i; +} + +static int rc2_set_asn1_type_and_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    long num; +    int i = 0, j; + +    if (type != NULL) { +        num = rc2_meth_to_magic(c); +        j = EVP_CIPHER_CTX_iv_length(c); +        i = ASN1_TYPE_set_int_octetstring(type, num, +                                          (unsigned char *)EVP_CIPHER_CTX_original_iv(c), +                                          j); +    } +    return (i); +} + +static int rc2_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    switch (type) { +    case EVP_CTRL_INIT: +        data(c)->key_bits = EVP_CIPHER_CTX_key_length(c) * 8; +        return 1; + +    case EVP_CTRL_GET_RC2_KEY_BITS: +        *(int *)ptr = data(c)->key_bits; +        return 1; + +    case EVP_CTRL_SET_RC2_KEY_BITS: +        if (arg > 0) { +            data(c)->key_bits = arg; +            return 1; +        } +        return 0; +# ifdef PBE_PRF_TEST +    case EVP_CTRL_PBE_PRF_NID: +        *(int *)ptr = NID_hmacWithMD5; +        return 1; +# endif + +    default: +        return -1; +    } +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_rc4.c b/openssl-1.1.0h/crypto/evp/e_rc4.c new file mode 100644 index 0000000..ea95dea --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_rc4.c @@ -0,0 +1,82 @@ +/* + * 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" + +#ifndef OPENSSL_NO_RC4 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/rc4.h> + +# include "internal/evp_int.h" + +typedef struct { +    RC4_KEY ks;                 /* working key */ +} EVP_RC4_KEY; + +# define data(ctx) ((EVP_RC4_KEY *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc); +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                      const unsigned char *in, size_t inl); +static const EVP_CIPHER r4_cipher = { +    NID_rc4, +    1, EVP_RC4_KEY_SIZE, 0, +    EVP_CIPH_VARIABLE_LENGTH, +    rc4_init_key, +    rc4_cipher, +    NULL, +    sizeof(EVP_RC4_KEY), +    NULL, +    NULL, +    NULL, +    NULL +}; + +static const EVP_CIPHER r4_40_cipher = { +    NID_rc4_40, +    1, 5 /* 40 bit */ , 0, +    EVP_CIPH_VARIABLE_LENGTH, +    rc4_init_key, +    rc4_cipher, +    NULL, +    sizeof(EVP_RC4_KEY), +    NULL, +    NULL, +    NULL, +    NULL +}; + +const EVP_CIPHER *EVP_rc4(void) +{ +    return (&r4_cipher); +} + +const EVP_CIPHER *EVP_rc4_40(void) +{ +    return (&r4_40_cipher); +} + +static int rc4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                        const unsigned char *iv, int enc) +{ +    RC4_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), key); +    return 1; +} + +static int rc4_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                      const unsigned char *in, size_t inl) +{ +    RC4(&data(ctx)->ks, inl, in, out); +    return 1; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_rc4_hmac_md5.c b/openssl-1.1.0h/crypto/evp/e_rc4_hmac_md5.c new file mode 100644 index 0000000..8ab18c1 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_rc4_hmac_md5.c @@ -0,0 +1,262 @@ +/* + * Copyright 2011-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> + +#include <stdio.h> +#include <string.h> + +#if !defined(OPENSSL_NO_RC4) && !defined(OPENSSL_NO_MD5) + +# include <openssl/crypto.h> +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/rc4.h> +# include <openssl/md5.h> +# include "internal/evp_int.h" + +typedef struct { +    RC4_KEY ks; +    MD5_CTX head, tail, md; +    size_t payload_length; +} EVP_RC4_HMAC_MD5; + +# define NO_PAYLOAD_LENGTH       ((size_t)-1) + +void rc4_md5_enc(RC4_KEY *key, const void *in0, void *out, +                 MD5_CTX *ctx, const void *inp, size_t blocks); + +# define data(ctx) ((EVP_RC4_HMAC_MD5 *)EVP_CIPHER_CTX_get_cipher_data(ctx)) + +static int rc4_hmac_md5_init_key(EVP_CIPHER_CTX *ctx, +                                 const unsigned char *inkey, +                                 const unsigned char *iv, int enc) +{ +    EVP_RC4_HMAC_MD5 *key = data(ctx); + +    RC4_set_key(&key->ks, EVP_CIPHER_CTX_key_length(ctx), inkey); + +    MD5_Init(&key->head);       /* handy when benchmarking */ +    key->tail = key->head; +    key->md = key->head; + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    return 1; +} + +# if     defined(RC4_ASM) && defined(MD5_ASM) &&     (	   \ +        defined(__x86_64)       || defined(__x86_64__)  || \ +        defined(_M_AMD64)       || defined(_M_X64)      ) +#  define STITCHED_CALL +# endif + +# if !defined(STITCHED_CALL) +#  define rc4_off 0 +#  define md5_off 0 +# endif + +static int rc4_hmac_md5_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                               const unsigned char *in, size_t len) +{ +    EVP_RC4_HMAC_MD5 *key = data(ctx); +# if defined(STITCHED_CALL) +    size_t rc4_off = 32 - 1 - (key->ks.x & (32 - 1)), /* 32 is $MOD from +                                                       * rc4_md5-x86_64.pl */ +        md5_off = MD5_CBLOCK - key->md.num, blocks; +    unsigned int l; +    extern unsigned int OPENSSL_ia32cap_P[]; +# endif +    size_t plen = key->payload_length; + +    if (plen != NO_PAYLOAD_LENGTH && len != (plen + MD5_DIGEST_LENGTH)) +        return 0; + +    if (EVP_CIPHER_CTX_encrypting(ctx)) { +        if (plen == NO_PAYLOAD_LENGTH) +            plen = len; +# if defined(STITCHED_CALL) +        /* cipher has to "fall behind" */ +        if (rc4_off > md5_off) +            md5_off += MD5_CBLOCK; + +        if (plen > md5_off && (blocks = (plen - md5_off) / MD5_CBLOCK) && +            (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) { +            MD5_Update(&key->md, in, md5_off); +            RC4(&key->ks, rc4_off, in, out); + +            rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off, +                        &key->md, in + md5_off, blocks); +            blocks *= MD5_CBLOCK; +            rc4_off += blocks; +            md5_off += blocks; +            key->md.Nh += blocks >> 29; +            key->md.Nl += blocks <<= 3; +            if (key->md.Nl < (unsigned int)blocks) +                key->md.Nh++; +        } else { +            rc4_off = 0; +            md5_off = 0; +        } +# endif +        MD5_Update(&key->md, in + md5_off, plen - md5_off); + +        if (plen != len) {      /* "TLS" mode of operation */ +            if (in != out) +                memcpy(out + rc4_off, in + rc4_off, plen - rc4_off); + +            /* calculate HMAC and append it to payload */ +            MD5_Final(out + plen, &key->md); +            key->md = key->tail; +            MD5_Update(&key->md, out + plen, MD5_DIGEST_LENGTH); +            MD5_Final(out + plen, &key->md); +            /* encrypt HMAC at once */ +            RC4(&key->ks, len - rc4_off, out + rc4_off, out + rc4_off); +        } else { +            RC4(&key->ks, len - rc4_off, in + rc4_off, out + rc4_off); +        } +    } else { +        unsigned char mac[MD5_DIGEST_LENGTH]; +# if defined(STITCHED_CALL) +        /* digest has to "fall behind" */ +        if (md5_off > rc4_off) +            rc4_off += 2 * MD5_CBLOCK; +        else +            rc4_off += MD5_CBLOCK; + +        if (len > rc4_off && (blocks = (len - rc4_off) / MD5_CBLOCK) && +            (OPENSSL_ia32cap_P[0] & (1 << 20)) == 0) { +            RC4(&key->ks, rc4_off, in, out); +            MD5_Update(&key->md, out, md5_off); + +            rc4_md5_enc(&key->ks, in + rc4_off, out + rc4_off, +                        &key->md, out + md5_off, blocks); +            blocks *= MD5_CBLOCK; +            rc4_off += blocks; +            md5_off += blocks; +            l = (key->md.Nl + (blocks << 3)) & 0xffffffffU; +            if (l < key->md.Nl) +                key->md.Nh++; +            key->md.Nl = l; +            key->md.Nh += blocks >> 29; +        } else { +            md5_off = 0; +            rc4_off = 0; +        } +# endif +        /* decrypt HMAC at once */ +        RC4(&key->ks, len - rc4_off, in + rc4_off, out + rc4_off); +        if (plen != NO_PAYLOAD_LENGTH) { /* "TLS" mode of operation */ +            MD5_Update(&key->md, out + md5_off, plen - md5_off); + +            /* calculate HMAC and verify it */ +            MD5_Final(mac, &key->md); +            key->md = key->tail; +            MD5_Update(&key->md, mac, MD5_DIGEST_LENGTH); +            MD5_Final(mac, &key->md); + +            if (CRYPTO_memcmp(out + plen, mac, MD5_DIGEST_LENGTH)) +                return 0; +        } else { +            MD5_Update(&key->md, out + md5_off, len - md5_off); +        } +    } + +    key->payload_length = NO_PAYLOAD_LENGTH; + +    return 1; +} + +static int rc4_hmac_md5_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, +                             void *ptr) +{ +    EVP_RC4_HMAC_MD5 *key = data(ctx); + +    switch (type) { +    case EVP_CTRL_AEAD_SET_MAC_KEY: +        { +            unsigned int i; +            unsigned char hmac_key[64]; + +            memset(hmac_key, 0, sizeof(hmac_key)); + +            if (arg > (int)sizeof(hmac_key)) { +                MD5_Init(&key->head); +                MD5_Update(&key->head, ptr, arg); +                MD5_Final(hmac_key, &key->head); +            } else { +                memcpy(hmac_key, ptr, arg); +            } + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36; /* ipad */ +            MD5_Init(&key->head); +            MD5_Update(&key->head, hmac_key, sizeof(hmac_key)); + +            for (i = 0; i < sizeof(hmac_key); i++) +                hmac_key[i] ^= 0x36 ^ 0x5c; /* opad */ +            MD5_Init(&key->tail); +            MD5_Update(&key->tail, hmac_key, sizeof(hmac_key)); + +            OPENSSL_cleanse(hmac_key, sizeof(hmac_key)); + +            return 1; +        } +    case EVP_CTRL_AEAD_TLS1_AAD: +        { +            unsigned char *p = ptr; +            unsigned int len; + +            if (arg != EVP_AEAD_TLS1_AAD_LEN) +                return -1; + +            len = p[arg - 2] << 8 | p[arg - 1]; + +            if (!EVP_CIPHER_CTX_encrypting(ctx)) { +                if (len < MD5_DIGEST_LENGTH) +                    return -1; +                len -= MD5_DIGEST_LENGTH; +                p[arg - 2] = len >> 8; +                p[arg - 1] = len; +            } +            key->payload_length = len; +            key->md = key->head; +            MD5_Update(&key->md, p, arg); + +            return MD5_DIGEST_LENGTH; +        } +    default: +        return -1; +    } +} + +static EVP_CIPHER r4_hmac_md5_cipher = { +# ifdef NID_rc4_hmac_md5 +    NID_rc4_hmac_md5, +# else +    NID_undef, +# endif +    1, EVP_RC4_KEY_SIZE, 0, +    EVP_CIPH_STREAM_CIPHER | EVP_CIPH_VARIABLE_LENGTH | +        EVP_CIPH_FLAG_AEAD_CIPHER, +    rc4_hmac_md5_init_key, +    rc4_hmac_md5_cipher, +    NULL, +    sizeof(EVP_RC4_HMAC_MD5), +    NULL, +    NULL, +    rc4_hmac_md5_ctrl, +    NULL +}; + +const EVP_CIPHER *EVP_rc4_hmac_md5(void) +{ +    return (&r4_hmac_md5_cipher); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_rc5.c b/openssl-1.1.0h/crypto/evp/e_rc5.c new file mode 100644 index 0000000..f69ba5b --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_rc5.c @@ -0,0 +1,74 @@ +/* + * 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" + +#ifndef OPENSSL_NO_RC5 + +# include <openssl/evp.h> +# include <internal/evp_int.h> +# include <openssl/objects.h> +# include "evp_locl.h" +# include <openssl/rc5.h> + +static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc); +static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr); + +typedef struct { +    int rounds;                 /* number of rounds */ +    RC5_32_KEY ks;              /* key schedule */ +} EVP_RC5_KEY; + +# define data(ctx)       EVP_C_DATA(EVP_RC5_KEY,ctx) + +IMPLEMENT_BLOCK_CIPHER(rc5_32_12_16, ks, RC5_32, EVP_RC5_KEY, NID_rc5, +                       8, RC5_32_KEY_LENGTH, 8, 64, +                       EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_CTRL_INIT, +                       r_32_12_16_init_key, NULL, NULL, NULL, rc5_ctrl) + +static int rc5_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ +    switch (type) { +    case EVP_CTRL_INIT: +        data(c)->rounds = RC5_12_ROUNDS; +        return 1; + +    case EVP_CTRL_GET_RC5_ROUNDS: +        *(int *)ptr = data(c)->rounds; +        return 1; + +    case EVP_CTRL_SET_RC5_ROUNDS: +        switch (arg) { +        case RC5_8_ROUNDS: +        case RC5_12_ROUNDS: +        case RC5_16_ROUNDS: +            data(c)->rounds = arg; +            return 1; + +        default: +            EVPerr(EVP_F_RC5_CTRL, EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS); +            return 0; +        } + +    default: +        return -1; +    } +} + +static int r_32_12_16_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                               const unsigned char *iv, int enc) +{ +    RC5_32_set_key(&data(ctx)->ks, EVP_CIPHER_CTX_key_length(ctx), +                   key, data(ctx)->rounds); +    return 1; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_seed.c b/openssl-1.1.0h/crypto/evp/e_seed.c new file mode 100644 index 0000000..40aec5f --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_seed.c @@ -0,0 +1,39 @@ +/* + * Copyright 2007-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_SEED +NON_EMPTY_TRANSLATION_UNIT +#else +# include <openssl/evp.h> +# include <openssl/err.h> +# include <string.h> +# include <assert.h> +# include <openssl/seed.h> +# include "internal/evp_int.h" + +static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc); + +typedef struct { +    SEED_KEY_SCHEDULE ks; +} EVP_SEED_KEY; + +IMPLEMENT_BLOCK_CIPHER(seed, ks, SEED, EVP_SEED_KEY, NID_seed, +                       16, 16, 16, 128, EVP_CIPH_FLAG_DEFAULT_ASN1, +                       seed_init_key, 0, 0, 0, 0) + +static int seed_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                         const unsigned char *iv, int enc) +{ +    SEED_set_key(key, &EVP_C_DATA(EVP_SEED_KEY,ctx)->ks); +    return 1; +} + +#endif diff --git a/openssl-1.1.0h/crypto/evp/e_xcbc_d.c b/openssl-1.1.0h/crypto/evp/e_xcbc_d.c new file mode 100644 index 0000000..effaf5c --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/e_xcbc_d.c @@ -0,0 +1,83 @@ +/* + * 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" + +#ifndef OPENSSL_NO_DES + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include "internal/evp_int.h" +# include <openssl/des.h> + +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc); +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl); + +typedef struct { +    DES_key_schedule ks;        /* key schedule */ +    DES_cblock inw; +    DES_cblock outw; +} DESX_CBC_KEY; + +# define data(ctx) EVP_C_DATA(DESX_CBC_KEY,ctx) + +static const EVP_CIPHER d_xcbc_cipher = { +    NID_desx_cbc, +    8, 24, 8, +    EVP_CIPH_CBC_MODE, +    desx_cbc_init_key, +    desx_cbc_cipher, +    NULL, +    sizeof(DESX_CBC_KEY), +    EVP_CIPHER_set_asn1_iv, +    EVP_CIPHER_get_asn1_iv, +    NULL, +    NULL +}; + +const EVP_CIPHER *EVP_desx_cbc(void) +{ +    return (&d_xcbc_cipher); +} + +static int desx_cbc_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, +                             const unsigned char *iv, int enc) +{ +    DES_cblock *deskey = (DES_cblock *)key; + +    DES_set_key_unchecked(deskey, &data(ctx)->ks); +    memcpy(&data(ctx)->inw[0], &key[8], 8); +    memcpy(&data(ctx)->outw[0], &key[16], 8); + +    return 1; +} + +static int desx_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +                           const unsigned char *in, size_t inl) +{ +    while (inl >= EVP_MAXCHUNK) { +        DES_xcbc_encrypt(in, out, (long)EVP_MAXCHUNK, &data(ctx)->ks, +                         (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                         &data(ctx)->inw, &data(ctx)->outw, +                         EVP_CIPHER_CTX_encrypting(ctx)); +        inl -= EVP_MAXCHUNK; +        in += EVP_MAXCHUNK; +        out += EVP_MAXCHUNK; +    } +    if (inl) +        DES_xcbc_encrypt(in, out, (long)inl, &data(ctx)->ks, +                         (DES_cblock *)EVP_CIPHER_CTX_iv_noconst(ctx), +                         &data(ctx)->inw, &data(ctx)->outw, +                         EVP_CIPHER_CTX_encrypting(ctx)); +    return 1; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/encode.c b/openssl-1.1.0h/crypto/evp/encode.c new file mode 100644 index 0000000..abb1044 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/encode.c @@ -0,0 +1,404 @@ +/* + * 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/evp.h> +#include "evp_locl.h" + +static unsigned char conv_ascii2bin(unsigned char a); +#ifndef CHARSET_EBCDIC +# define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f]) +#else +/* + * We assume that PEM encoded files are EBCDIC files (i.e., printable text + * files). Convert them here while decoding. When encoding, output is EBCDIC + * (text) format again. (No need for conversion in the conv_bin2ascii macro, + * as the underlying textstring data_bin2ascii[] is already EBCDIC) + */ +# define conv_bin2ascii(a)       (data_bin2ascii[(a)&0x3f]) +#endif + +/*- + * 64 char lines + * pad input with 0 + * left over chars are set to = + * 1 byte  => xx== + * 2 bytes => xxx= + * 3 bytes => xxxx + */ +#define BIN_PER_LINE    (64/4*3) +#define CHUNKS_PER_LINE (64/4) +#define CHAR_PER_LINE   (64+1) + +static const unsigned char data_bin2ascii[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\ +abcdefghijklmnopqrstuvwxyz0123456789+/"; + +/*- + * 0xF0 is a EOLN + * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing). + * 0xF2 is EOF + * 0xE0 is ignore at start of line. + * 0xFF is error + */ + +#define B64_EOLN                0xF0 +#define B64_CR                  0xF1 +#define B64_EOF                 0xF2 +#define B64_WS                  0xE0 +#define B64_ERROR               0xFF +#define B64_NOT_BASE64(a)       (((a)|0x13) == 0xF3) +#define B64_BASE64(a)           (!B64_NOT_BASE64(a)) + +static const unsigned char data_ascii2bin[128] = { +    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +    0xFF, 0xE0, 0xF0, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, +    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +    0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +    0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F, +    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, +    0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, +    0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, +    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, +    0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, +    0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, +    0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, +    0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, +    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, +}; + +#ifndef CHARSET_EBCDIC +static unsigned char conv_ascii2bin(unsigned char a) +{ +    if (a & 0x80) +        return B64_ERROR; +    return data_ascii2bin[a]; +} +#else +static unsigned char conv_ascii2bin(unsigned char a) +{ +    a = os_toascii[a]; +    if (a & 0x80) +        return B64_ERROR; +    return data_ascii2bin[a]; +} +#endif + +EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) +{ +    return OPENSSL_zalloc(sizeof(EVP_ENCODE_CTX)); +} + +void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) +{ +    OPENSSL_free(ctx); +} + +int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx) +{ +    memcpy(dctx, sctx, sizeof(EVP_ENCODE_CTX)); + +    return 1; +} + +int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx) +{ +    return ctx->num; +} + +void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) +{ +    ctx->length = 48; +    ctx->num = 0; +    ctx->line_num = 0; +} + +int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, +                      const unsigned char *in, int inl) +{ +    int i, j; +    size_t total = 0; + +    *outl = 0; +    if (inl <= 0) +        return 0; +    OPENSSL_assert(ctx->length <= (int)sizeof(ctx->enc_data)); +    if (ctx->length - ctx->num > inl) { +        memcpy(&(ctx->enc_data[ctx->num]), in, inl); +        ctx->num += inl; +        return 1; +    } +    if (ctx->num != 0) { +        i = ctx->length - ctx->num; +        memcpy(&(ctx->enc_data[ctx->num]), in, i); +        in += i; +        inl -= i; +        j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length); +        ctx->num = 0; +        out += j; +        *(out++) = '\n'; +        *out = '\0'; +        total = j + 1; +    } +    while (inl >= ctx->length && total <= INT_MAX) { +        j = EVP_EncodeBlock(out, in, ctx->length); +        in += ctx->length; +        inl -= ctx->length; +        out += j; +        *(out++) = '\n'; +        *out = '\0'; +        total += j + 1; +    } +    if (total > INT_MAX) { +        /* Too much output data! */ +        *outl = 0; +        return 0; +    } +    if (inl != 0) +        memcpy(&(ctx->enc_data[0]), in, inl); +    ctx->num = inl; +    *outl = total; + +    return 1; +} + +void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +{ +    unsigned int ret = 0; + +    if (ctx->num != 0) { +        ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num); +        out[ret++] = '\n'; +        out[ret] = '\0'; +        ctx->num = 0; +    } +    *outl = ret; +} + +int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen) +{ +    int i, ret = 0; +    unsigned long l; + +    for (i = dlen; i > 0; i -= 3) { +        if (i >= 3) { +            l = (((unsigned long)f[0]) << 16L) | +                (((unsigned long)f[1]) << 8L) | f[2]; +            *(t++) = conv_bin2ascii(l >> 18L); +            *(t++) = conv_bin2ascii(l >> 12L); +            *(t++) = conv_bin2ascii(l >> 6L); +            *(t++) = conv_bin2ascii(l); +        } else { +            l = ((unsigned long)f[0]) << 16L; +            if (i == 2) +                l |= ((unsigned long)f[1] << 8L); + +            *(t++) = conv_bin2ascii(l >> 18L); +            *(t++) = conv_bin2ascii(l >> 12L); +            *(t++) = (i == 1) ? '=' : conv_bin2ascii(l >> 6L); +            *(t++) = '='; +        } +        ret += 4; +        f += 3; +    } + +    *t = '\0'; +    return (ret); +} + +void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) +{ +    /* Only ctx->num is used during decoding. */ +    ctx->num = 0; +    ctx->length = 0; +    ctx->line_num = 0; +    ctx->expect_nl = 0; +} + +/*- + * -1 for error + *  0 for last line + *  1 for full line + * + * Note: even though EVP_DecodeUpdate attempts to detect and report end of + * content, the context doesn't currently remember it and will accept more data + * in the next call. Therefore, the caller is responsible for checking and + * rejecting a 0 return value in the middle of content. + * + * Note: even though EVP_DecodeUpdate has historically tried to detect end of + * content based on line length, this has never worked properly. Therefore, + * we now return 0 when one of the following is true: + *   - Padding or B64_EOF was detected and the last block is complete. + *   - Input has zero-length. + * -1 is returned if: + *   - Invalid characters are detected. + *   - There is extra trailing padding, or data after padding. + *   - B64_EOF is detected after an incomplete base64 block. + */ +int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl, +                     const unsigned char *in, int inl) +{ +    int seof = 0, eof = 0, rv = -1, ret = 0, i, v, tmp, n, decoded_len; +    unsigned char *d; + +    n = ctx->num; +    d = ctx->enc_data; + +    if (n > 0 && d[n - 1] == '=') { +        eof++; +        if (n > 1 && d[n - 2] == '=') +            eof++; +    } + +     /* Legacy behaviour: an empty input chunk signals end of input. */ +    if (inl == 0) { +        rv = 0; +        goto end; +    } + +    for (i = 0; i < inl; i++) { +        tmp = *(in++); +        v = conv_ascii2bin(tmp); +        if (v == B64_ERROR) { +            rv = -1; +            goto end; +        } + +        if (tmp == '=') { +            eof++; +        } else if (eof > 0 && B64_BASE64(v)) { +            /* More data after padding. */ +            rv = -1; +            goto end; +        } + +        if (eof > 2) { +            rv = -1; +            goto end; +        } + +        if (v == B64_EOF) { +            seof = 1; +            goto tail; +        } + +        /* Only save valid base64 characters. */ +        if (B64_BASE64(v)) { +            if (n >= 64) { +                /* +                 * We increment n once per loop, and empty the buffer as soon as +                 * we reach 64 characters, so this can only happen if someone's +                 * manually messed with the ctx. Refuse to write any more data. +                 */ +                rv = -1; +                goto end; +            } +            OPENSSL_assert(n < (int)sizeof(ctx->enc_data)); +            d[n++] = tmp; +        } + +        if (n == 64) { +            decoded_len = EVP_DecodeBlock(out, d, n); +            n = 0; +            if (decoded_len < 0 || eof > decoded_len) { +                rv = -1; +                goto end; +            } +            ret += decoded_len - eof; +            out += decoded_len - eof; +        } +    } + +    /* +     * Legacy behaviour: if the current line is a full base64-block (i.e., has +     * 0 mod 4 base64 characters), it is processed immediately. We keep this +     * behaviour as applications may not be calling EVP_DecodeFinal properly. +     */ +tail: +    if (n > 0) { +        if ((n & 3) == 0) { +            decoded_len = EVP_DecodeBlock(out, d, n); +            n = 0; +            if (decoded_len < 0 || eof > decoded_len) { +                rv = -1; +                goto end; +            } +            ret += (decoded_len - eof); +        } else if (seof) { +            /* EOF in the middle of a base64 block. */ +            rv = -1; +            goto end; +        } +    } + +    rv = seof || (n == 0 && eof) ? 0 : 1; +end: +    /* Legacy behaviour. This should probably rather be zeroed on error. */ +    *outl = ret; +    ctx->num = n; +    return (rv); +} + +int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n) +{ +    int i, ret = 0, a, b, c, d; +    unsigned long l; + +    /* trim white space from the start of the line. */ +    while ((conv_ascii2bin(*f) == B64_WS) && (n > 0)) { +        f++; +        n--; +    } + +    /* +     * strip off stuff at the end of the line ascii2bin values B64_WS, +     * B64_EOLN, B64_EOLN and B64_EOF +     */ +    while ((n > 3) && (B64_NOT_BASE64(conv_ascii2bin(f[n - 1])))) +        n--; + +    if (n % 4 != 0) +        return (-1); + +    for (i = 0; i < n; i += 4) { +        a = conv_ascii2bin(*(f++)); +        b = conv_ascii2bin(*(f++)); +        c = conv_ascii2bin(*(f++)); +        d = conv_ascii2bin(*(f++)); +        if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) +            return (-1); +        l = ((((unsigned long)a) << 18L) | +             (((unsigned long)b) << 12L) | +             (((unsigned long)c) << 6L) | (((unsigned long)d))); +        *(t++) = (unsigned char)(l >> 16L) & 0xff; +        *(t++) = (unsigned char)(l >> 8L) & 0xff; +        *(t++) = (unsigned char)(l) & 0xff; +        ret += 3; +    } +    return (ret); +} + +int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl) +{ +    int i; + +    *outl = 0; +    if (ctx->num != 0) { +        i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num); +        if (i < 0) +            return (-1); +        ctx->num = 0; +        *outl = i; +        return (1); +    } else +        return (1); +} diff --git a/openssl-1.1.0h/crypto/evp/evp_cnf.c b/openssl-1.1.0h/crypto/evp/evp_cnf.c new file mode 100644 index 0000000..71d13b8 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_cnf.c @@ -0,0 +1,65 @@ +/* + * 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/x509.h> +#include <openssl/x509v3.h> + +/* Algorithm configuration module. */ + +static int alg_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) { +        EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_ERROR_LOADING_SECTION); +        return 0; +    } +    for (i = 0; i < sk_CONF_VALUE_num(sktmp); i++) { +        oval = sk_CONF_VALUE_value(sktmp, i); +        if (strcmp(oval->name, "fips_mode") == 0) { +            int m; +            if (!X509V3_get_value_bool(oval, &m)) { +                EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_INVALID_FIPS_MODE); +                return 0; +            } +            if (m > 0) { +#ifdef OPENSSL_FIPS +                if (!FIPS_mode() && !FIPS_mode_set(1)) { +                    EVPerr(EVP_F_ALG_MODULE_INIT, +                           EVP_R_ERROR_SETTING_FIPS_MODE); +                    return 0; +                } +#else +                EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_FIPS_MODE_NOT_SUPPORTED); +                return 0; +#endif +            } +        } else { +            EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_UNKNOWN_OPTION); +            ERR_add_error_data(4, "name=", oval->name, +                               ", value=", oval->value); +        } + +    } +    return 1; +} + +void EVP_add_alg_module(void) +{ +    CONF_module_add("alg_section", alg_module_init, 0); +} diff --git a/openssl-1.1.0h/crypto/evp/evp_enc.c b/openssl-1.1.0h/crypto/evp/evp_enc.c new file mode 100644 index 0000000..e5807ed --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_enc.c @@ -0,0 +1,642 @@ +/* + * 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 <assert.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/err.h> +#include <openssl/rand.h> +#include <openssl/engine.h> +#include "internal/evp_int.h" +#include "evp_locl.h" + +int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c) +{ +    if (c == NULL) +        return 1; +    if (c->cipher != NULL) { +        if (c->cipher->cleanup && !c->cipher->cleanup(c)) +            return 0; +        /* Cleanse cipher context data */ +        if (c->cipher_data && c->cipher->ctx_size) +            OPENSSL_cleanse(c->cipher_data, c->cipher->ctx_size); +    } +    OPENSSL_free(c->cipher_data); +#ifndef OPENSSL_NO_ENGINE +    ENGINE_finish(c->engine); +#endif +    memset(c, 0, sizeof(*c)); +    return 1; +} + +EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) +{ +    return OPENSSL_zalloc(sizeof(EVP_CIPHER_CTX)); +} + +void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx) +{ +    EVP_CIPHER_CTX_reset(ctx); +    OPENSSL_free(ctx); +} + +int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                   const unsigned char *key, const unsigned char *iv, int enc) +{ +    if (cipher != NULL) +        EVP_CIPHER_CTX_reset(ctx); +    return EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc); +} + +int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                      ENGINE *impl, const unsigned char *key, +                      const unsigned char *iv, int enc) +{ +    if (enc == -1) +        enc = ctx->encrypt; +    else { +        if (enc) +            enc = 1; +        ctx->encrypt = enc; +    } +#ifndef OPENSSL_NO_ENGINE +    /* +     * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so +     * this context may already have an ENGINE! Try to avoid releasing the +     * previous handle, re-querying for an ENGINE, and having a +     * reinitialisation, when it may all be unnecessary. +     */ +    if (ctx->engine && ctx->cipher +        && (cipher == NULL || cipher->nid == ctx->cipher->nid)) +        goto skip_to_init; +#endif +    if (cipher) { +        /* +         * Ensure a context left lying around from last time is cleared (the +         * previous check attempted to avoid this if the same ENGINE and +         * EVP_CIPHER could be used). +         */ +        if (ctx->cipher) { +            unsigned long flags = ctx->flags; +            EVP_CIPHER_CTX_reset(ctx); +            /* Restore encrypt and flags */ +            ctx->encrypt = enc; +            ctx->flags = flags; +        } +#ifndef OPENSSL_NO_ENGINE +        if (impl) { +            if (!ENGINE_init(impl)) { +                EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); +                return 0; +            } +        } else +            /* Ask if an ENGINE is reserved for this job */ +            impl = ENGINE_get_cipher_engine(cipher->nid); +        if (impl) { +            /* There's an ENGINE for this job ... (apparently) */ +            const EVP_CIPHER *c = ENGINE_get_cipher(impl, cipher->nid); +            if (!c) { +                /* +                 * One positive side-effect of US's export control history, +                 * is that we should at least be able to avoid using US +                 * misspellings of "initialisation"? +                 */ +                EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); +                return 0; +            } +            /* We'll use the ENGINE's private cipher definition */ +            cipher = c; +            /* +             * Store the ENGINE functional reference so we know 'cipher' came +             * from an ENGINE and we need to release it when done. +             */ +            ctx->engine = impl; +        } else +            ctx->engine = NULL; +#endif + +        ctx->cipher = cipher; +        if (ctx->cipher->ctx_size) { +            ctx->cipher_data = OPENSSL_zalloc(ctx->cipher->ctx_size); +            if (ctx->cipher_data == NULL) { +                ctx->cipher = NULL; +                EVPerr(EVP_F_EVP_CIPHERINIT_EX, ERR_R_MALLOC_FAILURE); +                return 0; +            } +        } else { +            ctx->cipher_data = NULL; +        } +        ctx->key_len = cipher->key_len; +        /* Preserve wrap enable flag, zero everything else */ +        ctx->flags &= EVP_CIPHER_CTX_FLAG_WRAP_ALLOW; +        if (ctx->cipher->flags & EVP_CIPH_CTRL_INIT) { +            if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_INIT, 0, NULL)) { +                ctx->cipher = NULL; +                EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); +                return 0; +            } +        } +    } else if (!ctx->cipher) { +        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_NO_CIPHER_SET); +        return 0; +    } +#ifndef OPENSSL_NO_ENGINE + skip_to_init: +#endif +    /* we assume block size is a power of 2 in *cryptUpdate */ +    OPENSSL_assert(ctx->cipher->block_size == 1 +                   || ctx->cipher->block_size == 8 +                   || ctx->cipher->block_size == 16); + +    if (!(ctx->flags & EVP_CIPHER_CTX_FLAG_WRAP_ALLOW) +        && EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_WRAP_MODE) { +        EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_WRAP_MODE_NOT_ALLOWED); +        return 0; +    } + +    if (!(EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(ctx)) & EVP_CIPH_CUSTOM_IV)) { +        switch (EVP_CIPHER_CTX_mode(ctx)) { + +        case EVP_CIPH_STREAM_CIPHER: +        case EVP_CIPH_ECB_MODE: +            break; + +        case EVP_CIPH_CFB_MODE: +        case EVP_CIPH_OFB_MODE: + +            ctx->num = 0; +            /* fall-through */ + +        case EVP_CIPH_CBC_MODE: + +            OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) <= +                           (int)sizeof(ctx->iv)); +            if (iv) +                memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); +            memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); +            break; + +        case EVP_CIPH_CTR_MODE: +            ctx->num = 0; +            /* Don't reuse IV for CTR mode */ +            if (iv) +                memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx)); +            break; + +        default: +            return 0; +        } +    } + +    if (key || (ctx->cipher->flags & EVP_CIPH_ALWAYS_CALL_INIT)) { +        if (!ctx->cipher->init(ctx, key, iv, enc)) +            return 0; +    } +    ctx->buf_len = 0; +    ctx->final_used = 0; +    ctx->block_mask = ctx->cipher->block_size - 1; +    return 1; +} + +int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, +                     const unsigned char *in, int inl) +{ +    if (ctx->encrypt) +        return EVP_EncryptUpdate(ctx, out, outl, in, inl); +    else +        return EVP_DecryptUpdate(ctx, out, outl, in, inl); +} + +int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    if (ctx->encrypt) +        return EVP_EncryptFinal_ex(ctx, out, outl); +    else +        return EVP_DecryptFinal_ex(ctx, out, outl); +} + +int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    if (ctx->encrypt) +        return EVP_EncryptFinal(ctx, out, outl); +    else +        return EVP_DecryptFinal(ctx, out, outl); +} + +int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                    const unsigned char *key, const unsigned char *iv) +{ +    return EVP_CipherInit(ctx, cipher, key, iv, 1); +} + +int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                       ENGINE *impl, const unsigned char *key, +                       const unsigned char *iv) +{ +    return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 1); +} + +int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                    const unsigned char *key, const unsigned char *iv) +{ +    return EVP_CipherInit(ctx, cipher, key, iv, 0); +} + +int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, +                       ENGINE *impl, const unsigned char *key, +                       const unsigned char *iv) +{ +    return EVP_CipherInit_ex(ctx, cipher, impl, key, iv, 0); +} + +/* + * According to the letter of standard difference between pointers + * is specified to be valid only within same object. This makes + * it formally challenging to determine if input and output buffers + * are not partially overlapping with standard pointer arithmetic. + */ +#ifdef PTRDIFF_T +# undef PTRDIFF_T +#endif +#if defined(OPENSSL_SYS_VMS) && __INITIAL_POINTER_SIZE==64 +/* + * Then we have VMS that distinguishes itself by adhering to + * sizeof(size_t)==4 even in 64-bit builds, which means that + * difference between two pointers might be truncated to 32 bits. + * In the context one can even wonder how comparison for + * equality is implemented. To be on the safe side we adhere to + * PTRDIFF_T even for comparison for equality. + */ +# define PTRDIFF_T uint64_t +#else +# define PTRDIFF_T size_t +#endif + +int is_partially_overlapping(const void *ptr1, const void *ptr2, int len) +{ +    PTRDIFF_T diff = (PTRDIFF_T)ptr1-(PTRDIFF_T)ptr2; +    /* +     * Check for partially overlapping buffers. [Binary logical +     * operations are used instead of boolean to minimize number +     * of conditional branches.] +     */ +    int overlapped = (len > 0) & (diff != 0) & ((diff < (PTRDIFF_T)len) | +                                                (diff > (0 - (PTRDIFF_T)len))); + +    return overlapped; +} + +int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, +                      const unsigned char *in, int inl) +{ +    int i, j, bl, cmpl = inl; + +    if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) +        cmpl = (cmpl + 7) / 8; + +    bl = ctx->cipher->block_size; + +    if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { +        /* If block size > 1 then the cipher will have to do this check */ +        if (bl == 1 && is_partially_overlapping(out, in, cmpl)) { +            EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); +            return 0; +        } + +        i = ctx->cipher->do_cipher(ctx, out, in, inl); +        if (i < 0) +            return 0; +        else +            *outl = i; +        return 1; +    } + +    if (inl <= 0) { +        *outl = 0; +        return inl == 0; +    } +    if (is_partially_overlapping(out + ctx->buf_len, in, cmpl)) { +        EVPerr(EVP_F_EVP_ENCRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); +        return 0; +    } + +    if (ctx->buf_len == 0 && (inl & (ctx->block_mask)) == 0) { +        if (ctx->cipher->do_cipher(ctx, out, in, inl)) { +            *outl = inl; +            return 1; +        } else { +            *outl = 0; +            return 0; +        } +    } +    i = ctx->buf_len; +    OPENSSL_assert(bl <= (int)sizeof(ctx->buf)); +    if (i != 0) { +        if (bl - i > inl) { +            memcpy(&(ctx->buf[i]), in, inl); +            ctx->buf_len += inl; +            *outl = 0; +            return 1; +        } else { +            j = bl - i; +            memcpy(&(ctx->buf[i]), in, j); +            inl -= j; +            in += j; +            if (!ctx->cipher->do_cipher(ctx, out, ctx->buf, bl)) +                return 0; +            out += bl; +            *outl = bl; +        } +    } else +        *outl = 0; +    i = inl & (bl - 1); +    inl -= i; +    if (inl > 0) { +        if (!ctx->cipher->do_cipher(ctx, out, in, inl)) +            return 0; +        *outl += inl; +    } + +    if (i != 0) +        memcpy(ctx->buf, &(in[inl]), i); +    ctx->buf_len = i; +    return 1; +} + +int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int ret; +    ret = EVP_EncryptFinal_ex(ctx, out, outl); +    return ret; +} + +int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int n, ret; +    unsigned int i, b, bl; + +    if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { +        ret = ctx->cipher->do_cipher(ctx, out, NULL, 0); +        if (ret < 0) +            return 0; +        else +            *outl = ret; +        return 1; +    } + +    b = ctx->cipher->block_size; +    OPENSSL_assert(b <= sizeof(ctx->buf)); +    if (b == 1) { +        *outl = 0; +        return 1; +    } +    bl = ctx->buf_len; +    if (ctx->flags & EVP_CIPH_NO_PADDING) { +        if (bl) { +            EVPerr(EVP_F_EVP_ENCRYPTFINAL_EX, +                   EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); +            return 0; +        } +        *outl = 0; +        return 1; +    } + +    n = b - bl; +    for (i = bl; i < b; i++) +        ctx->buf[i] = n; +    ret = ctx->cipher->do_cipher(ctx, out, ctx->buf, b); + +    if (ret) +        *outl = b; + +    return ret; +} + +int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, +                      const unsigned char *in, int inl) +{ +    int fix_len, cmpl = inl; +    unsigned int b; + +    b = ctx->cipher->block_size; + +    if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) +        cmpl = (cmpl + 7) / 8; + +    if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { +        if (b == 1 && is_partially_overlapping(out, in, cmpl)) { +            EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); +            return 0; +        } + +        fix_len = ctx->cipher->do_cipher(ctx, out, in, inl); +        if (fix_len < 0) { +            *outl = 0; +            return 0; +        } else +            *outl = fix_len; +        return 1; +    } + +    if (inl <= 0) { +        *outl = 0; +        return inl == 0; +    } + +    if (ctx->flags & EVP_CIPH_NO_PADDING) +        return EVP_EncryptUpdate(ctx, out, outl, in, inl); + +    OPENSSL_assert(b <= sizeof(ctx->final)); + +    if (ctx->final_used) { +        /* see comment about PTRDIFF_T comparison above */ +        if (((PTRDIFF_T)out == (PTRDIFF_T)in) +            || is_partially_overlapping(out, in, b)) { +            EVPerr(EVP_F_EVP_DECRYPTUPDATE, EVP_R_PARTIALLY_OVERLAPPING); +            return 0; +        } +        memcpy(out, ctx->final, b); +        out += b; +        fix_len = 1; +    } else +        fix_len = 0; + +    if (!EVP_EncryptUpdate(ctx, out, outl, in, inl)) +        return 0; + +    /* +     * if we have 'decrypted' a multiple of block size, make sure we have a +     * copy of this last block +     */ +    if (b > 1 && !ctx->buf_len) { +        *outl -= b; +        ctx->final_used = 1; +        memcpy(ctx->final, &out[*outl], b); +    } else +        ctx->final_used = 0; + +    if (fix_len) +        *outl += b; + +    return 1; +} + +int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int ret; +    ret = EVP_DecryptFinal_ex(ctx, out, outl); +    return ret; +} + +int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int i, n; +    unsigned int b; +    *outl = 0; + +    if (ctx->cipher->flags & EVP_CIPH_FLAG_CUSTOM_CIPHER) { +        i = ctx->cipher->do_cipher(ctx, out, NULL, 0); +        if (i < 0) +            return 0; +        else +            *outl = i; +        return 1; +    } + +    b = ctx->cipher->block_size; +    if (ctx->flags & EVP_CIPH_NO_PADDING) { +        if (ctx->buf_len) { +            EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, +                   EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH); +            return 0; +        } +        *outl = 0; +        return 1; +    } +    if (b > 1) { +        if (ctx->buf_len || !ctx->final_used) { +            EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_WRONG_FINAL_BLOCK_LENGTH); +            return (0); +        } +        OPENSSL_assert(b <= sizeof(ctx->final)); + +        /* +         * The following assumes that the ciphertext has been authenticated. +         * Otherwise it provides a padding oracle. +         */ +        n = ctx->final[b - 1]; +        if (n == 0 || n > (int)b) { +            EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT); +            return (0); +        } +        for (i = 0; i < n; i++) { +            if (ctx->final[--b] != n) { +                EVPerr(EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT); +                return (0); +            } +        } +        n = ctx->cipher->block_size - n; +        for (i = 0; i < n; i++) +            out[i] = ctx->final[i]; +        *outl = n; +    } else +        *outl = 0; +    return (1); +} + +int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) +{ +    if (c->cipher->flags & EVP_CIPH_CUSTOM_KEY_LENGTH) +        return EVP_CIPHER_CTX_ctrl(c, EVP_CTRL_SET_KEY_LENGTH, keylen, NULL); +    if (c->key_len == keylen) +        return 1; +    if ((keylen > 0) && (c->cipher->flags & EVP_CIPH_VARIABLE_LENGTH)) { +        c->key_len = keylen; +        return 1; +    } +    EVPerr(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, EVP_R_INVALID_KEY_LENGTH); +    return 0; +} + +int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *ctx, int pad) +{ +    if (pad) +        ctx->flags &= ~EVP_CIPH_NO_PADDING; +    else +        ctx->flags |= EVP_CIPH_NO_PADDING; +    return 1; +} + +int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) +{ +    int ret; +    if (!ctx->cipher) { +        EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_NO_CIPHER_SET); +        return 0; +    } + +    if (!ctx->cipher->ctrl) { +        EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_NOT_IMPLEMENTED); +        return 0; +    } + +    ret = ctx->cipher->ctrl(ctx, type, arg, ptr); +    if (ret == -1) { +        EVPerr(EVP_F_EVP_CIPHER_CTX_CTRL, +               EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED); +        return 0; +    } +    return ret; +} + +int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) +{ +    if (ctx->cipher->flags & EVP_CIPH_RAND_KEY) +        return EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_RAND_KEY, 0, key); +    if (RAND_bytes(key, ctx->key_len) <= 0) +        return 0; +    return 1; +} + +int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) +{ +    if ((in == NULL) || (in->cipher == NULL)) { +        EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INPUT_NOT_INITIALIZED); +        return 0; +    } +#ifndef OPENSSL_NO_ENGINE +    /* Make sure it's safe to copy a cipher context using an ENGINE */ +    if (in->engine && !ENGINE_init(in->engine)) { +        EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB); +        return 0; +    } +#endif + +    EVP_CIPHER_CTX_reset(out); +    memcpy(out, in, sizeof(*out)); + +    if (in->cipher_data && in->cipher->ctx_size) { +        out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size); +        if (out->cipher_data == NULL) { +            out->cipher = NULL; +            EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size); +    } + +    if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) +        if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) { +            out->cipher = NULL; +            EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, EVP_R_INITIALIZATION_ERROR); +            return 0; +        } +    return 1; +} diff --git a/openssl-1.1.0h/crypto/evp/evp_err.c b/openssl-1.1.0h/crypto/evp/evp_err.c new file mode 100644 index 0000000..c4b163f --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_err.c @@ -0,0 +1,186 @@ +/* + * 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/evp.h> + +/* BEGIN ERROR CODES */ +#ifndef OPENSSL_NO_ERR + +# define ERR_FUNC(func) ERR_PACK(ERR_LIB_EVP,func,0) +# define ERR_REASON(reason) ERR_PACK(ERR_LIB_EVP,0,reason) + +static ERR_STRING_DATA EVP_str_functs[] = { +    {ERR_FUNC(EVP_F_AESNI_INIT_KEY), "aesni_init_key"}, +    {ERR_FUNC(EVP_F_AES_INIT_KEY), "aes_init_key"}, +    {ERR_FUNC(EVP_F_AES_OCB_CIPHER), "aes_ocb_cipher"}, +    {ERR_FUNC(EVP_F_AES_T4_INIT_KEY), "aes_t4_init_key"}, +    {ERR_FUNC(EVP_F_AES_WRAP_CIPHER), "aes_wrap_cipher"}, +    {ERR_FUNC(EVP_F_ALG_MODULE_INIT), "alg_module_init"}, +    {ERR_FUNC(EVP_F_CAMELLIA_INIT_KEY), "camellia_init_key"}, +    {ERR_FUNC(EVP_F_CHACHA20_POLY1305_CTRL), "chacha20_poly1305_ctrl"}, +    {ERR_FUNC(EVP_F_CMLL_T4_INIT_KEY), "cmll_t4_init_key"}, +    {ERR_FUNC(EVP_F_DES_EDE3_WRAP_CIPHER), "des_ede3_wrap_cipher"}, +    {ERR_FUNC(EVP_F_DO_SIGVER_INIT), "do_sigver_init"}, +    {ERR_FUNC(EVP_F_EVP_CIPHERINIT_EX), "EVP_CipherInit_ex"}, +    {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_COPY), "EVP_CIPHER_CTX_copy"}, +    {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_CTRL), "EVP_CIPHER_CTX_ctrl"}, +    {ERR_FUNC(EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH), +     "EVP_CIPHER_CTX_set_key_length"}, +    {ERR_FUNC(EVP_F_EVP_DECRYPTFINAL_EX), "EVP_DecryptFinal_ex"}, +    {ERR_FUNC(EVP_F_EVP_DECRYPTUPDATE), "EVP_DecryptUpdate"}, +    {ERR_FUNC(EVP_F_EVP_DIGESTINIT_EX), "EVP_DigestInit_ex"}, +    {ERR_FUNC(EVP_F_EVP_ENCRYPTFINAL_EX), "EVP_EncryptFinal_ex"}, +    {ERR_FUNC(EVP_F_EVP_ENCRYPTUPDATE), "EVP_EncryptUpdate"}, +    {ERR_FUNC(EVP_F_EVP_MD_CTX_COPY_EX), "EVP_MD_CTX_copy_ex"}, +    {ERR_FUNC(EVP_F_EVP_MD_SIZE), "EVP_MD_size"}, +    {ERR_FUNC(EVP_F_EVP_OPENINIT), "EVP_OpenInit"}, +    {ERR_FUNC(EVP_F_EVP_PBE_ALG_ADD), "EVP_PBE_alg_add"}, +    {ERR_FUNC(EVP_F_EVP_PBE_ALG_ADD_TYPE), "EVP_PBE_alg_add_type"}, +    {ERR_FUNC(EVP_F_EVP_PBE_CIPHERINIT), "EVP_PBE_CipherInit"}, +    {ERR_FUNC(EVP_F_EVP_PBE_SCRYPT), "EVP_PBE_scrypt"}, +    {ERR_FUNC(EVP_F_EVP_PKCS82PKEY), "EVP_PKCS82PKEY"}, +    {ERR_FUNC(EVP_F_EVP_PKEY2PKCS8), "EVP_PKEY2PKCS8"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_ASN1_ADD0), "EVP_PKEY_asn1_add0"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_COPY_PARAMETERS), "EVP_PKEY_copy_parameters"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL), "EVP_PKEY_CTX_ctrl"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_CTX_CTRL_STR), "EVP_PKEY_CTX_ctrl_str"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_CTX_DUP), "EVP_PKEY_CTX_dup"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT), "EVP_PKEY_decrypt"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_INIT), "EVP_PKEY_decrypt_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_OLD), "EVP_PKEY_decrypt_old"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DERIVE), "EVP_PKEY_derive"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DERIVE_INIT), "EVP_PKEY_derive_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_DERIVE_SET_PEER), "EVP_PKEY_derive_set_peer"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT), "EVP_PKEY_encrypt"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT_INIT), "EVP_PKEY_encrypt_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT_OLD), "EVP_PKEY_encrypt_old"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_DH), "EVP_PKEY_get0_DH"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_DSA), "EVP_PKEY_get0_DSA"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_EC_KEY), "EVP_PKEY_get0_EC_KEY"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_HMAC), "EVP_PKEY_get0_hmac"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_GET0_RSA), "EVP_PKEY_get0_RSA"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN), "EVP_PKEY_keygen"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_KEYGEN_INIT), "EVP_PKEY_keygen_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_NEW), "EVP_PKEY_new"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_PARAMGEN), "EVP_PKEY_paramgen"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_PARAMGEN_INIT), "EVP_PKEY_paramgen_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_SET1_ENGINE), "EVP_PKEY_set1_engine"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_SIGN), "EVP_PKEY_sign"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_SIGN_INIT), "EVP_PKEY_sign_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_VERIFY), "EVP_PKEY_verify"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_VERIFY_INIT), "EVP_PKEY_verify_init"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_VERIFY_RECOVER), "EVP_PKEY_verify_recover"}, +    {ERR_FUNC(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT), +     "EVP_PKEY_verify_recover_init"}, +    {ERR_FUNC(EVP_F_EVP_SIGNFINAL), "EVP_SignFinal"}, +    {ERR_FUNC(EVP_F_EVP_VERIFYFINAL), "EVP_VerifyFinal"}, +    {ERR_FUNC(EVP_F_INT_CTX_NEW), "int_ctx_new"}, +    {ERR_FUNC(EVP_F_PKCS5_PBE_KEYIVGEN), "PKCS5_PBE_keyivgen"}, +    {ERR_FUNC(EVP_F_PKCS5_V2_PBE_KEYIVGEN), "PKCS5_v2_PBE_keyivgen"}, +    {ERR_FUNC(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN), "PKCS5_v2_PBKDF2_keyivgen"}, +    {ERR_FUNC(EVP_F_PKCS5_V2_SCRYPT_KEYIVGEN), "PKCS5_v2_scrypt_keyivgen"}, +    {ERR_FUNC(EVP_F_PKEY_SET_TYPE), "pkey_set_type"}, +    {ERR_FUNC(EVP_F_RC2_MAGIC_TO_METH), "rc2_magic_to_meth"}, +    {ERR_FUNC(EVP_F_RC5_CTRL), "rc5_ctrl"}, +    {0, NULL} +}; + +static ERR_STRING_DATA EVP_str_reasons[] = { +    {ERR_REASON(EVP_R_AES_KEY_SETUP_FAILED), "aes key setup failed"}, +    {ERR_REASON(EVP_R_BAD_DECRYPT), "bad decrypt"}, +    {ERR_REASON(EVP_R_BUFFER_TOO_SMALL), "buffer too small"}, +    {ERR_REASON(EVP_R_CAMELLIA_KEY_SETUP_FAILED), +     "camellia key setup failed"}, +    {ERR_REASON(EVP_R_CIPHER_PARAMETER_ERROR), "cipher parameter error"}, +    {ERR_REASON(EVP_R_COMMAND_NOT_SUPPORTED), "command not supported"}, +    {ERR_REASON(EVP_R_COPY_ERROR), "copy error"}, +    {ERR_REASON(EVP_R_CTRL_NOT_IMPLEMENTED), "ctrl not implemented"}, +    {ERR_REASON(EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED), +     "ctrl operation not implemented"}, +    {ERR_REASON(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH), +     "data not multiple of block length"}, +    {ERR_REASON(EVP_R_DECODE_ERROR), "decode error"}, +    {ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES), "different key types"}, +    {ERR_REASON(EVP_R_DIFFERENT_PARAMETERS), "different parameters"}, +    {ERR_REASON(EVP_R_ERROR_LOADING_SECTION), "error loading section"}, +    {ERR_REASON(EVP_R_ERROR_SETTING_FIPS_MODE), "error setting fips mode"}, +    {ERR_REASON(EVP_R_EXPECTING_AN_HMAC_KEY), "expecting an hmac key"}, +    {ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY), "expecting an rsa key"}, +    {ERR_REASON(EVP_R_EXPECTING_A_DH_KEY), "expecting a dh key"}, +    {ERR_REASON(EVP_R_EXPECTING_A_DSA_KEY), "expecting a dsa key"}, +    {ERR_REASON(EVP_R_EXPECTING_A_EC_KEY), "expecting a ec key"}, +    {ERR_REASON(EVP_R_FIPS_MODE_NOT_SUPPORTED), "fips mode not supported"}, +    {ERR_REASON(EVP_R_ILLEGAL_SCRYPT_PARAMETERS), +     "illegal scrypt parameters"}, +    {ERR_REASON(EVP_R_INITIALIZATION_ERROR), "initialization error"}, +    {ERR_REASON(EVP_R_INPUT_NOT_INITIALIZED), "input not initialized"}, +    {ERR_REASON(EVP_R_INVALID_DIGEST), "invalid digest"}, +    {ERR_REASON(EVP_R_INVALID_FIPS_MODE), "invalid fips mode"}, +    {ERR_REASON(EVP_R_INVALID_KEY), "invalid key"}, +    {ERR_REASON(EVP_R_INVALID_KEY_LENGTH), "invalid key length"}, +    {ERR_REASON(EVP_R_INVALID_OPERATION), "invalid operation"}, +    {ERR_REASON(EVP_R_KEYGEN_FAILURE), "keygen failure"}, +    {ERR_REASON(EVP_R_MEMORY_LIMIT_EXCEEDED), "memory limit exceeded"}, +    {ERR_REASON(EVP_R_MESSAGE_DIGEST_IS_NULL), "message digest is null"}, +    {ERR_REASON(EVP_R_METHOD_NOT_SUPPORTED), "method not supported"}, +    {ERR_REASON(EVP_R_MISSING_PARAMETERS), "missing parameters"}, +    {ERR_REASON(EVP_R_NO_CIPHER_SET), "no cipher set"}, +    {ERR_REASON(EVP_R_NO_DEFAULT_DIGEST), "no default digest"}, +    {ERR_REASON(EVP_R_NO_DIGEST_SET), "no digest set"}, +    {ERR_REASON(EVP_R_NO_KEY_SET), "no key set"}, +    {ERR_REASON(EVP_R_NO_OPERATION_SET), "no operation set"}, +    {ERR_REASON(EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE), +     "operation not supported for this keytype"}, +    {ERR_REASON(EVP_R_OPERATON_NOT_INITIALIZED), "operaton not initialized"}, +    {ERR_REASON(EVP_R_PARTIALLY_OVERLAPPING), +     "partially overlapping buffers"}, +    {ERR_REASON(EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED), +     "pkey application asn1 method already registered"}, +    {ERR_REASON(EVP_R_PKEY_ASN1_METHOD_ALREADY_REGISTERED), +     "pkey asn1 method already registered"}, +    {ERR_REASON(EVP_R_PRIVATE_KEY_DECODE_ERROR), "private key decode error"}, +    {ERR_REASON(EVP_R_PRIVATE_KEY_ENCODE_ERROR), "private key encode error"}, +    {ERR_REASON(EVP_R_PUBLIC_KEY_NOT_RSA), "public key not rsa"}, +    {ERR_REASON(EVP_R_UNKNOWN_CIPHER), "unknown cipher"}, +    {ERR_REASON(EVP_R_UNKNOWN_DIGEST), "unknown digest"}, +    {ERR_REASON(EVP_R_UNKNOWN_OPTION), "unknown option"}, +    {ERR_REASON(EVP_R_UNKNOWN_PBE_ALGORITHM), "unknown pbe algorithm"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_ALGORITHM), "unsupported algorithm"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_CIPHER), "unsupported cipher"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_KEYLENGTH), "unsupported keylength"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION), +     "unsupported key derivation function"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_KEY_SIZE), "unsupported key size"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_NUMBER_OF_ROUNDS), +     "unsupported number of rounds"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_PRF), "unsupported prf"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM), +     "unsupported private key algorithm"}, +    {ERR_REASON(EVP_R_UNSUPPORTED_SALT_TYPE), "unsupported salt type"}, +    {ERR_REASON(EVP_R_WRAP_MODE_NOT_ALLOWED), "wrap mode not allowed"}, +    {ERR_REASON(EVP_R_WRONG_FINAL_BLOCK_LENGTH), "wrong final block length"}, +    {0, NULL} +}; + +#endif + +int ERR_load_EVP_strings(void) +{ +#ifndef OPENSSL_NO_ERR + +    if (ERR_func_error_string(EVP_str_functs[0].error) == NULL) { +        ERR_load_strings(0, EVP_str_functs); +        ERR_load_strings(0, EVP_str_reasons); +    } +#endif +    return 1; +} diff --git a/openssl-1.1.0h/crypto/evp/evp_key.c b/openssl-1.1.0h/crypto/evp/evp_key.c new file mode 100644 index 0000000..5201130 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_key.c @@ -0,0 +1,152 @@ +/* + * 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/x509.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/ui.h> + +#ifndef OPENSSL_NO_UI +/* should be init to zeros. */ +static char prompt_string[80]; + +void EVP_set_pw_prompt(const char *prompt) +{ +    if (prompt == NULL) +        prompt_string[0] = '\0'; +    else { +        strncpy(prompt_string, prompt, 79); +        prompt_string[79] = '\0'; +    } +} + +char *EVP_get_pw_prompt(void) +{ +    if (prompt_string[0] == '\0') +        return (NULL); +    else +        return (prompt_string); +} + +/* + * For historical reasons, the standard function for reading passwords is in + * the DES library -- if someone ever wants to disable DES, this function + * will fail + */ +int EVP_read_pw_string(char *buf, int len, const char *prompt, int verify) +{ +    return EVP_read_pw_string_min(buf, 0, len, prompt, verify); +} + +int EVP_read_pw_string_min(char *buf, int min, int len, const char *prompt, +                           int verify) +{ +    int ret = -1; +    char buff[BUFSIZ]; +    UI *ui; + +    if ((prompt == NULL) && (prompt_string[0] != '\0')) +        prompt = prompt_string; +    ui = UI_new(); +    if (ui == NULL) +        return ret; +    if (UI_add_input_string(ui, prompt, 0, buf, min, +                            (len >= BUFSIZ) ? BUFSIZ - 1 : len) < 0 +        || (verify +            && UI_add_verify_string(ui, prompt, 0, buff, min, +                                    (len >= BUFSIZ) ? BUFSIZ - 1 : len, +                                    buf) < 0)) +        goto end; +    ret = UI_process(ui); +    OPENSSL_cleanse(buff, BUFSIZ); + end: +    UI_free(ui); +    return ret; +} +#endif /* OPENSSL_NO_UI */ + +int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md, +                   const unsigned char *salt, const unsigned char *data, +                   int datal, int count, unsigned char *key, +                   unsigned char *iv) +{ +    EVP_MD_CTX *c; +    unsigned char md_buf[EVP_MAX_MD_SIZE]; +    int niv, nkey, addmd = 0; +    unsigned int mds = 0, i; +    int rv = 0; +    nkey = EVP_CIPHER_key_length(type); +    niv = EVP_CIPHER_iv_length(type); +    OPENSSL_assert(nkey <= EVP_MAX_KEY_LENGTH); +    OPENSSL_assert(niv <= EVP_MAX_IV_LENGTH); + +    if (data == NULL) +        return (nkey); + +    c = EVP_MD_CTX_new(); +    if (c == NULL) +        goto err; +    for (;;) { +        if (!EVP_DigestInit_ex(c, md, NULL)) +            goto err; +        if (addmd++) +            if (!EVP_DigestUpdate(c, &(md_buf[0]), mds)) +                goto err; +        if (!EVP_DigestUpdate(c, data, datal)) +            goto err; +        if (salt != NULL) +            if (!EVP_DigestUpdate(c, salt, PKCS5_SALT_LEN)) +                goto err; +        if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds)) +            goto err; + +        for (i = 1; i < (unsigned int)count; i++) { +            if (!EVP_DigestInit_ex(c, md, NULL)) +                goto err; +            if (!EVP_DigestUpdate(c, &(md_buf[0]), mds)) +                goto err; +            if (!EVP_DigestFinal_ex(c, &(md_buf[0]), &mds)) +                goto err; +        } +        i = 0; +        if (nkey) { +            for (;;) { +                if (nkey == 0) +                    break; +                if (i == mds) +                    break; +                if (key != NULL) +                    *(key++) = md_buf[i]; +                nkey--; +                i++; +            } +        } +        if (niv && (i != mds)) { +            for (;;) { +                if (niv == 0) +                    break; +                if (i == mds) +                    break; +                if (iv != NULL) +                    *(iv++) = md_buf[i]; +                niv--; +                i++; +            } +        } +        if ((nkey == 0) && (niv == 0)) +            break; +    } +    rv = EVP_CIPHER_key_length(type); + err: +    EVP_MD_CTX_free(c); +    OPENSSL_cleanse(md_buf, sizeof(md_buf)); +    return rv; +} diff --git a/openssl-1.1.0h/crypto/evp/evp_lib.c b/openssl-1.1.0h/crypto/evp/evp_lib.c new file mode 100644 index 0000000..0c76db5 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_lib.c @@ -0,0 +1,497 @@ +/* + * 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 "internal/evp_int.h" +#include "evp_locl.h" + +int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    int ret; + +    if (c->cipher->set_asn1_parameters != NULL) +        ret = c->cipher->set_asn1_parameters(c, type); +    else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) { +        switch (EVP_CIPHER_CTX_mode(c)) { +        case EVP_CIPH_WRAP_MODE: +            if (EVP_CIPHER_CTX_nid(c) == NID_id_smime_alg_CMS3DESwrap) +                ASN1_TYPE_set(type, V_ASN1_NULL, NULL); +            ret = 1; +            break; + +        case EVP_CIPH_GCM_MODE: +        case EVP_CIPH_CCM_MODE: +        case EVP_CIPH_XTS_MODE: +        case EVP_CIPH_OCB_MODE: +            ret = -1; +            break; + +        default: +            ret = EVP_CIPHER_set_asn1_iv(c, type); +        } +    } else +        ret = -1; +    return (ret); +} + +int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    int ret; + +    if (c->cipher->get_asn1_parameters != NULL) +        ret = c->cipher->get_asn1_parameters(c, type); +    else if (c->cipher->flags & EVP_CIPH_FLAG_DEFAULT_ASN1) { +        switch (EVP_CIPHER_CTX_mode(c)) { + +        case EVP_CIPH_WRAP_MODE: +            ret = 1; +            break; + +        case EVP_CIPH_GCM_MODE: +        case EVP_CIPH_CCM_MODE: +        case EVP_CIPH_XTS_MODE: +        case EVP_CIPH_OCB_MODE: +            ret = -1; +            break; + +        default: +            ret = EVP_CIPHER_get_asn1_iv(c, type); +            break; +        } +    } else +        ret = -1; +    return (ret); +} + +int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    int i = 0; +    unsigned int l; + +    if (type != NULL) { +        l = EVP_CIPHER_CTX_iv_length(c); +        OPENSSL_assert(l <= sizeof(c->iv)); +        i = ASN1_TYPE_get_octetstring(type, c->oiv, l); +        if (i != (int)l) +            return (-1); +        else if (i > 0) +            memcpy(c->iv, c->oiv, l); +    } +    return (i); +} + +int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) +{ +    int i = 0; +    unsigned int j; + +    if (type != NULL) { +        j = EVP_CIPHER_CTX_iv_length(c); +        OPENSSL_assert(j <= sizeof(c->iv)); +        i = ASN1_TYPE_set_octetstring(type, c->oiv, j); +    } +    return (i); +} + +/* Convert the various cipher NIDs and dummies to a proper OID NID */ +int EVP_CIPHER_type(const EVP_CIPHER *ctx) +{ +    int nid; +    ASN1_OBJECT *otmp; +    nid = EVP_CIPHER_nid(ctx); + +    switch (nid) { + +    case NID_rc2_cbc: +    case NID_rc2_64_cbc: +    case NID_rc2_40_cbc: + +        return NID_rc2_cbc; + +    case NID_rc4: +    case NID_rc4_40: + +        return NID_rc4; + +    case NID_aes_128_cfb128: +    case NID_aes_128_cfb8: +    case NID_aes_128_cfb1: + +        return NID_aes_128_cfb128; + +    case NID_aes_192_cfb128: +    case NID_aes_192_cfb8: +    case NID_aes_192_cfb1: + +        return NID_aes_192_cfb128; + +    case NID_aes_256_cfb128: +    case NID_aes_256_cfb8: +    case NID_aes_256_cfb1: + +        return NID_aes_256_cfb128; + +    case NID_des_cfb64: +    case NID_des_cfb8: +    case NID_des_cfb1: + +        return NID_des_cfb64; + +    case NID_des_ede3_cfb64: +    case NID_des_ede3_cfb8: +    case NID_des_ede3_cfb1: + +        return NID_des_cfb64; + +    default: +        /* Check it has an OID and it is valid */ +        otmp = OBJ_nid2obj(nid); +        if (OBJ_get0_data(otmp) == NULL) +            nid = NID_undef; +        ASN1_OBJECT_free(otmp); +        return nid; +    } +} + +int EVP_CIPHER_block_size(const EVP_CIPHER *e) +{ +    return e->block_size; +} + +int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->cipher->block_size; +} + +int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *e) +{ +    return e->ctx_size; +} + +int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, +               const unsigned char *in, unsigned int inl) +{ +    return ctx->cipher->do_cipher(ctx, out, in, inl); +} + +const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->cipher; +} + +int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->encrypt; +} + +unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher) +{ +    return cipher->flags; +} + +void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->app_data; +} + +void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data) +{ +    ctx->app_data = data; +} + +void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->cipher_data; +} + +void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data) +{ +    void *old_cipher_data; + +    old_cipher_data = ctx->cipher_data; +    ctx->cipher_data = cipher_data; + +    return old_cipher_data; +} + +int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) +{ +    return cipher->iv_len; +} + +int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->cipher->iv_len; +} + +const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->oiv; +} + +const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->iv; +} + +unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx) +{ +    return ctx->iv; +} + +unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx) +{ +    return ctx->buf; +} + +int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->num; +} + +void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num) +{ +    ctx->num = num; +} + +int EVP_CIPHER_key_length(const EVP_CIPHER *cipher) +{ +    return cipher->key_len; +} + +int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->key_len; +} + +int EVP_CIPHER_nid(const EVP_CIPHER *cipher) +{ +    return cipher->nid; +} + +int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx) +{ +    return ctx->cipher->nid; +} + +int EVP_MD_block_size(const EVP_MD *md) +{ +    return md->block_size; +} + +int EVP_MD_type(const EVP_MD *md) +{ +    return md->type; +} + +int EVP_MD_pkey_type(const EVP_MD *md) +{ +    return md->pkey_type; +} + +int EVP_MD_size(const EVP_MD *md) +{ +    if (!md) { +        EVPerr(EVP_F_EVP_MD_SIZE, EVP_R_MESSAGE_DIGEST_IS_NULL); +        return -1; +    } +    return md->md_size; +} + +unsigned long EVP_MD_flags(const EVP_MD *md) +{ +    return md->flags; +} + +EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type) +{ +    EVP_MD *md = OPENSSL_zalloc(sizeof(*md)); + +    if (md != NULL) { +        md->type = md_type; +        md->pkey_type = pkey_type; +    } +    return md; +} +EVP_MD *EVP_MD_meth_dup(const EVP_MD *md) +{ +    EVP_MD *to = EVP_MD_meth_new(md->type, md->pkey_type); + +    if (to != NULL) +        memcpy(to, md, sizeof(*to)); +    return to; +} +void EVP_MD_meth_free(EVP_MD *md) +{ +    OPENSSL_free(md); +} +int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize) +{ +    md->block_size = blocksize; +    return 1; +} +int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize) +{ +    md->md_size = resultsize; +    return 1; +} +int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize) +{ +    md->ctx_size = datasize; +    return 1; +} +int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags) +{ +    md->flags = flags; +    return 1; +} +int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx)) +{ +    md->init = init; +    return 1; +} +int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx, +                                                     const void *data, +                                                     size_t count)) +{ +    md->update = update; +    return 1; +} +int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx, +                                                   unsigned char *md)) +{ +    md->final = final; +    return 1; +} +int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to, +                                                 const EVP_MD_CTX *from)) +{ +    md->copy = copy; +    return 1; +} +int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx)) +{ +    md->cleanup = cleanup; +    return 1; +} +int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd, +                                                 int p1, void *p2)) +{ +    md->md_ctrl = ctrl; +    return 1; +} + +int EVP_MD_meth_get_input_blocksize(const EVP_MD *md) +{ +    return md->block_size; +} +int EVP_MD_meth_get_result_size(const EVP_MD *md) +{ +    return md->md_size; +} +int EVP_MD_meth_get_app_datasize(const EVP_MD *md) +{ +    return md->ctx_size; +} +unsigned long EVP_MD_meth_get_flags(const EVP_MD *md) +{ +    return md->flags; +} +int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx) +{ +    return md->init; +} +int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx, +                                                const void *data, +                                                size_t count) +{ +    return md->update; +} +int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx, +                                               unsigned char *md) +{ +    return md->final; +} +int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to, +                                              const EVP_MD_CTX *from) +{ +    return md->copy; +} +int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx) +{ +    return md->cleanup; +} +int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd, +                                              int p1, void *p2) +{ +    return md->md_ctrl; +} + +const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx) +{ +    if (!ctx) +        return NULL; +    return ctx->digest; +} + +EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) +{ +    return ctx->pctx; +} + +void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) +{ +    return ctx->md_data; +} + +int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx, +                                             const void *data, size_t count) +{ +    return ctx->update; +} + +void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx, +                              int (*update) (EVP_MD_CTX *ctx, +                                             const void *data, size_t count)) +{ +    ctx->update = update; +} + +void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags) +{ +    ctx->flags |= flags; +} + +void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags) +{ +    ctx->flags &= ~flags; +} + +int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags) +{ +    return (ctx->flags & flags); +} + +void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags) +{ +    ctx->flags |= flags; +} + +void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags) +{ +    ctx->flags &= ~flags; +} + +int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags) +{ +    return (ctx->flags & flags); +} diff --git a/openssl-1.1.0h/crypto/evp/evp_locl.h b/openssl-1.1.0h/crypto/evp/evp_locl.h new file mode 100644 index 0000000..209577b --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_locl.h @@ -0,0 +1,68 @@ +/* + * 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 + */ + +/* EVP_MD_CTX related stuff */ + +struct evp_md_ctx_st { +    const EVP_MD *digest; +    ENGINE *engine;             /* functional reference if 'digest' is +                                 * ENGINE-provided */ +    unsigned long flags; +    void *md_data; +    /* Public key context for sign/verify */ +    EVP_PKEY_CTX *pctx; +    /* Update function: usually copied from EVP_MD */ +    int (*update) (EVP_MD_CTX *ctx, const void *data, size_t count); +} /* EVP_MD_CTX */ ; + +struct evp_cipher_ctx_st { +    const EVP_CIPHER *cipher; +    ENGINE *engine;             /* functional reference if 'cipher' is +                                 * ENGINE-provided */ +    int encrypt;                /* encrypt or decrypt */ +    int buf_len;                /* number we have left */ +    unsigned char oiv[EVP_MAX_IV_LENGTH]; /* original iv */ +    unsigned char iv[EVP_MAX_IV_LENGTH]; /* working iv */ +    unsigned char buf[EVP_MAX_BLOCK_LENGTH]; /* saved partial block */ +    int num;                    /* used by cfb/ofb/ctr mode */ +    /* FIXME: Should this even exist? It appears unused */ +    void *app_data;             /* application stuff */ +    int key_len;                /* May change for variable length cipher */ +    unsigned long flags;        /* Various flags */ +    void *cipher_data;          /* per EVP data */ +    int final_used; +    int block_mask; +    unsigned char final[EVP_MAX_BLOCK_LENGTH]; /* possible final block */ +} /* EVP_CIPHER_CTX */ ; + +int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, +                             int passlen, ASN1_TYPE *param, +                             const EVP_CIPHER *c, const EVP_MD *md, +                             int en_de); + +struct evp_Encode_Ctx_st { +    /* number saved in a partial encode/decode */ +    int num; +    /* +     * The length is either the output line length (in input bytes) or the +     * shortest input line length that is ok.  Once decoding begins, the +     * length is adjusted up each time a longer line is decoded +     */ +    int length; +    /* data to encode */ +    unsigned char enc_data[80]; +    /* number read on current line */ +    int line_num; +    int expect_nl; +}; + +typedef struct evp_pbe_st EVP_PBE_CTL; +DEFINE_STACK_OF(EVP_PBE_CTL) + +int is_partially_overlapping(const void *ptr1, const void *ptr2, int len); diff --git a/openssl-1.1.0h/crypto/evp/evp_pbe.c b/openssl-1.1.0h/crypto/evp/evp_pbe.c new file mode 100644 index 0000000..eb7344c --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_pbe.c @@ -0,0 +1,259 @@ +/* + * 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/evp.h> +#include <openssl/pkcs12.h> +#include <openssl/x509.h> +#include "evp_locl.h" + +/* Password based encryption (PBE) functions */ + +/* Setup a cipher context from a PBE algorithm */ + +struct evp_pbe_st { +    int pbe_type; +    int pbe_nid; +    int cipher_nid; +    int md_nid; +    EVP_PBE_KEYGEN *keygen; +}; + +static STACK_OF(EVP_PBE_CTL) *pbe_algs; + +static const EVP_PBE_CTL builtin_pbe[] = { +    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndDES_CBC, +     NID_des_cbc, NID_md2, PKCS5_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndDES_CBC, +     NID_des_cbc, NID_md5, PKCS5_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndRC2_CBC, +     NID_rc2_64_cbc, NID_sha1, PKCS5_PBE_keyivgen}, + +    {EVP_PBE_TYPE_OUTER, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen}, + +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC4, +     NID_rc4, NID_sha1, PKCS12_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC4, +     NID_rc4_40, NID_sha1, PKCS12_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And3_Key_TripleDES_CBC, +     NID_des_ede3_cbc, NID_sha1, PKCS12_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And2_Key_TripleDES_CBC, +     NID_des_ede_cbc, NID_sha1, PKCS12_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And128BitRC2_CBC, +     NID_rc2_cbc, NID_sha1, PKCS12_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbe_WithSHA1And40BitRC2_CBC, +     NID_rc2_40_cbc, NID_sha1, PKCS12_PBE_keyivgen}, + +    {EVP_PBE_TYPE_OUTER, NID_pbes2, -1, -1, PKCS5_v2_PBE_keyivgen}, + +    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD2AndRC2_CBC, +     NID_rc2_64_cbc, NID_md2, PKCS5_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbeWithMD5AndRC2_CBC, +     NID_rc2_64_cbc, NID_md5, PKCS5_PBE_keyivgen}, +    {EVP_PBE_TYPE_OUTER, NID_pbeWithSHA1AndDES_CBC, +     NID_des_cbc, NID_sha1, PKCS5_PBE_keyivgen}, + +    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA1, -1, NID_sha1, 0}, +    {EVP_PBE_TYPE_PRF, NID_hmacWithMD5, -1, NID_md5, 0}, +    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA224, -1, NID_sha224, 0}, +    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA256, -1, NID_sha256, 0}, +    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA384, -1, NID_sha384, 0}, +    {EVP_PBE_TYPE_PRF, NID_hmacWithSHA512, -1, NID_sha512, 0}, +    {EVP_PBE_TYPE_PRF, NID_id_HMACGostR3411_94, -1, NID_id_GostR3411_94, 0}, +    {EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_256, -1, +     NID_id_GostR3411_2012_256, 0}, +    {EVP_PBE_TYPE_PRF, NID_id_tc26_hmac_gost_3411_2012_512, -1, +     NID_id_GostR3411_2012_512, 0}, +    {EVP_PBE_TYPE_KDF, NID_id_pbkdf2, -1, -1, PKCS5_v2_PBKDF2_keyivgen}, +#ifndef OPENSSL_NO_SCRYPT +    {EVP_PBE_TYPE_KDF, NID_id_scrypt, -1, -1, PKCS5_v2_scrypt_keyivgen} +#endif +}; + +int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen, +                       ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) +{ +    const EVP_CIPHER *cipher; +    const EVP_MD *md; +    int cipher_nid, md_nid; +    EVP_PBE_KEYGEN *keygen; + +    if (!EVP_PBE_find(EVP_PBE_TYPE_OUTER, OBJ_obj2nid(pbe_obj), +                      &cipher_nid, &md_nid, &keygen)) { +        char obj_tmp[80]; +        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_PBE_ALGORITHM); +        if (!pbe_obj) +            OPENSSL_strlcpy(obj_tmp, "NULL", sizeof(obj_tmp)); +        else +            i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), pbe_obj); +        ERR_add_error_data(2, "TYPE=", obj_tmp); +        return 0; +    } + +    if (!pass) +        passlen = 0; +    else if (passlen == -1) +        passlen = strlen(pass); + +    if (cipher_nid == -1) +        cipher = NULL; +    else { +        cipher = EVP_get_cipherbynid(cipher_nid); +        if (!cipher) { +            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_CIPHER); +            return 0; +        } +    } + +    if (md_nid == -1) +        md = NULL; +    else { +        md = EVP_get_digestbynid(md_nid); +        if (!md) { +            EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_UNKNOWN_DIGEST); +            return 0; +        } +    } + +    if (!keygen(ctx, pass, passlen, param, cipher, md, en_de)) { +        EVPerr(EVP_F_EVP_PBE_CIPHERINIT, EVP_R_KEYGEN_FAILURE); +        return 0; +    } +    return 1; +} + +DECLARE_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2); + +static int pbe2_cmp(const EVP_PBE_CTL *pbe1, const EVP_PBE_CTL *pbe2) +{ +    int ret = pbe1->pbe_type - pbe2->pbe_type; +    if (ret) +        return ret; +    else +        return pbe1->pbe_nid - pbe2->pbe_nid; +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(EVP_PBE_CTL, EVP_PBE_CTL, pbe2); + +static int pbe_cmp(const EVP_PBE_CTL *const *a, const EVP_PBE_CTL *const *b) +{ +    int ret = (*a)->pbe_type - (*b)->pbe_type; +    if (ret) +        return ret; +    else +        return (*a)->pbe_nid - (*b)->pbe_nid; +} + +/* Add a PBE algorithm */ + +int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid, +                         int md_nid, EVP_PBE_KEYGEN *keygen) +{ +    EVP_PBE_CTL *pbe_tmp; + +    if (pbe_algs == NULL) { +        pbe_algs = sk_EVP_PBE_CTL_new(pbe_cmp); +        if (pbe_algs == NULL) +            goto err; +    } + +    if ((pbe_tmp = OPENSSL_malloc(sizeof(*pbe_tmp))) == NULL) +        goto err; + +    pbe_tmp->pbe_type = pbe_type; +    pbe_tmp->pbe_nid = pbe_nid; +    pbe_tmp->cipher_nid = cipher_nid; +    pbe_tmp->md_nid = md_nid; +    pbe_tmp->keygen = keygen; + +    if (!sk_EVP_PBE_CTL_push(pbe_algs, pbe_tmp)) { +        OPENSSL_free(pbe_tmp); +        goto err; +    } +    return 1; + + err: +    EVPerr(EVP_F_EVP_PBE_ALG_ADD_TYPE, ERR_R_MALLOC_FAILURE); +    return 0; +} + +int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md, +                    EVP_PBE_KEYGEN *keygen) +{ +    int cipher_nid, md_nid; + +    if (cipher) +        cipher_nid = EVP_CIPHER_nid(cipher); +    else +        cipher_nid = -1; +    if (md) +        md_nid = EVP_MD_type(md); +    else +        md_nid = -1; + +    return EVP_PBE_alg_add_type(EVP_PBE_TYPE_OUTER, nid, +                                cipher_nid, md_nid, keygen); +} + +int EVP_PBE_find(int type, int pbe_nid, +                 int *pcnid, int *pmnid, EVP_PBE_KEYGEN **pkeygen) +{ +    EVP_PBE_CTL *pbetmp = NULL, pbelu; +    int i; +    if (pbe_nid == NID_undef) +        return 0; + +    pbelu.pbe_type = type; +    pbelu.pbe_nid = pbe_nid; + +    if (pbe_algs) { +        i = sk_EVP_PBE_CTL_find(pbe_algs, &pbelu); +        if (i != -1) +            pbetmp = sk_EVP_PBE_CTL_value(pbe_algs, i); +    } +    if (pbetmp == NULL) { +        pbetmp = OBJ_bsearch_pbe2(&pbelu, builtin_pbe, OSSL_NELEM(builtin_pbe)); +    } +    if (pbetmp == NULL) +        return 0; +    if (pcnid) +        *pcnid = pbetmp->cipher_nid; +    if (pmnid) +        *pmnid = pbetmp->md_nid; +    if (pkeygen) +        *pkeygen = pbetmp->keygen; +    return 1; +} + +static void free_evp_pbe_ctl(EVP_PBE_CTL *pbe) +{ +    OPENSSL_free(pbe); +} + +void EVP_PBE_cleanup(void) +{ +    sk_EVP_PBE_CTL_pop_free(pbe_algs, free_evp_pbe_ctl); +    pbe_algs = NULL; +} + +int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num) +{ +    const EVP_PBE_CTL *tpbe; + +    if (num >= OSSL_NELEM(builtin_pbe)) +        return 0; + +    tpbe = builtin_pbe + num; +    if (ptype) +        *ptype = tpbe->pbe_type; +    if (ppbe_nid) +        *ppbe_nid = tpbe->pbe_nid; +    return 1; +} diff --git a/openssl-1.1.0h/crypto/evp/evp_pkey.c b/openssl-1.1.0h/crypto/evp/evp_pkey.c new file mode 100644 index 0000000..81bffa6 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/evp_pkey.c @@ -0,0 +1,150 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/x509.h> +#include <openssl/rand.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/x509_int.h" + +/* Extract a private key from a PKCS8 structure */ + +EVP_PKEY *EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8) +{ +    EVP_PKEY *pkey = NULL; +    const ASN1_OBJECT *algoid; +    char obj_tmp[80]; + +    if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) +        return NULL; + +    if ((pkey = EVP_PKEY_new()) == NULL) { +        EVPerr(EVP_F_EVP_PKCS82PKEY, ERR_R_MALLOC_FAILURE); +        return NULL; +    } + +    if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { +        EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); +        i2t_ASN1_OBJECT(obj_tmp, 80, algoid); +        ERR_add_error_data(2, "TYPE=", obj_tmp); +        goto error; +    } + +    if (pkey->ameth->priv_decode) { +        if (!pkey->ameth->priv_decode(pkey, p8)) { +            EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_PRIVATE_KEY_DECODE_ERROR); +            goto error; +        } +    } else { +        EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_METHOD_NOT_SUPPORTED); +        goto error; +    } + +    return pkey; + + error: +    EVP_PKEY_free(pkey); +    return NULL; +} + +/* Turn a private key into a PKCS8 structure */ + +PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) +{ +    PKCS8_PRIV_KEY_INFO *p8 = PKCS8_PRIV_KEY_INFO_new(); +    if (p8  == NULL) { +        EVPerr(EVP_F_EVP_PKEY2PKCS8, ERR_R_MALLOC_FAILURE); +        return NULL; +    } + +    if (pkey->ameth) { +        if (pkey->ameth->priv_encode) { +            if (!pkey->ameth->priv_encode(p8, pkey)) { +                EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_PRIVATE_KEY_ENCODE_ERROR); +                goto error; +            } +        } else { +            EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_METHOD_NOT_SUPPORTED); +            goto error; +        } +    } else { +        EVPerr(EVP_F_EVP_PKEY2PKCS8, EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); +        goto error; +    } +    RAND_add(p8->pkey->data, p8->pkey->length, 0.0); +    return p8; + error: +    PKCS8_PRIV_KEY_INFO_free(p8); +    return NULL; +} + +/* EVP_PKEY attribute functions */ + +int EVP_PKEY_get_attr_count(const EVP_PKEY *key) +{ +    return X509at_get_attr_count(key->attributes); +} + +int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid, int lastpos) +{ +    return X509at_get_attr_by_NID(key->attributes, nid, lastpos); +} + +int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, const ASN1_OBJECT *obj, +                             int lastpos) +{ +    return X509at_get_attr_by_OBJ(key->attributes, obj, lastpos); +} + +X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc) +{ +    return X509at_get_attr(key->attributes, loc); +} + +X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc) +{ +    return X509at_delete_attr(key->attributes, loc); +} + +int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr) +{ +    if (X509at_add1_attr(&key->attributes, attr)) +        return 1; +    return 0; +} + +int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key, +                              const ASN1_OBJECT *obj, int type, +                              const unsigned char *bytes, int len) +{ +    if (X509at_add1_attr_by_OBJ(&key->attributes, obj, type, bytes, len)) +        return 1; +    return 0; +} + +int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key, +                              int nid, int type, +                              const unsigned char *bytes, int len) +{ +    if (X509at_add1_attr_by_NID(&key->attributes, nid, type, bytes, len)) +        return 1; +    return 0; +} + +int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key, +                              const char *attrname, int type, +                              const unsigned char *bytes, int len) +{ +    if (X509at_add1_attr_by_txt(&key->attributes, attrname, type, bytes, len)) +        return 1; +    return 0; +} diff --git a/openssl-1.1.0h/crypto/evp/m_md2.c b/openssl-1.1.0h/crypto/evp/m_md2.c new file mode 100644 index 0000000..c4e28ae --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_md2.c @@ -0,0 +1,56 @@ +/* + * 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" + +#ifndef OPENSSL_NO_MD2 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/md2.h> +# include <openssl/rsa.h> + +#include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return MD2_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return MD2_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return MD2_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md2_md = { +    NID_md2, +    NID_md2WithRSAEncryption, +    MD2_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    MD2_BLOCK, +    sizeof(EVP_MD *) + sizeof(MD2_CTX), +}; + +const EVP_MD *EVP_md2(void) +{ +    return &md2_md; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_md4.c b/openssl-1.1.0h/crypto/evp/m_md4.c new file mode 100644 index 0000000..f3decaa --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_md4.c @@ -0,0 +1,55 @@ +/* + * 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" + +#ifndef OPENSSL_NO_MD4 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/md4.h> +# include <openssl/rsa.h> +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return MD4_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return MD4_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return MD4_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md4_md = { +    NID_md4, +    NID_md4WithRSAEncryption, +    MD4_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    MD4_CBLOCK, +    sizeof(EVP_MD *) + sizeof(MD4_CTX), +}; + +const EVP_MD *EVP_md4(void) +{ +    return (&md4_md); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_md5.c b/openssl-1.1.0h/crypto/evp/m_md5.c new file mode 100644 index 0000000..f4dc0c4 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_md5.c @@ -0,0 +1,55 @@ +/* + * 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" + +#ifndef OPENSSL_NO_MD5 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/md5.h> +# include <openssl/rsa.h> +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return MD5_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return MD5_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return MD5_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD md5_md = { +    NID_md5, +    NID_md5WithRSAEncryption, +    MD5_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    MD5_CBLOCK, +    sizeof(EVP_MD *) + sizeof(MD5_CTX), +}; + +const EVP_MD *EVP_md5(void) +{ +    return (&md5_md); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_md5_sha1.c b/openssl-1.1.0h/crypto/evp/m_md5_sha1.c new file mode 100644 index 0000000..2d98886 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_md5_sha1.c @@ -0,0 +1,142 @@ +/* + * 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 + */ + +#if !defined(OPENSSL_NO_MD5) + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/md5.h> +# include <openssl/sha.h> +# include "internal/cryptlib.h" +# include "internal/evp_int.h" +# include <openssl/rsa.h> + +struct md5_sha1_ctx { +    MD5_CTX md5; +    SHA_CTX sha1; +}; + +static int init(EVP_MD_CTX *ctx) +{ +    struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); +    if (!MD5_Init(&mctx->md5)) +        return 0; +    return SHA1_Init(&mctx->sha1); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); +    if (!MD5_Update(&mctx->md5, data, count)) +        return 0; +    return SHA1_Update(&mctx->sha1, data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    struct md5_sha1_ctx *mctx = EVP_MD_CTX_md_data(ctx); +    if (!MD5_Final(md, &mctx->md5)) +        return 0; +    return SHA1_Final(md + MD5_DIGEST_LENGTH, &mctx->sha1); +} + +static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) +{ +    unsigned char padtmp[48]; +    unsigned char md5tmp[MD5_DIGEST_LENGTH]; +    unsigned char sha1tmp[SHA_DIGEST_LENGTH]; +    struct md5_sha1_ctx *mctx; + +    if (cmd != EVP_CTRL_SSL3_MASTER_SECRET) +        return -2; + +    if (ctx == NULL) +        return 0; + +    mctx = EVP_MD_CTX_md_data(ctx); + +    /* SSLv3 client auth handling: see RFC-6101 5.6.8 */ +    if (mslen != 48) +        return 0; + +    /* At this point hash contains all handshake messages, update +     * with master secret and pad_1. +     */ + +    if (update(ctx, ms, mslen) <= 0) +        return 0; + +    /* Set padtmp to pad_1 value */ +    memset(padtmp, 0x36, sizeof(padtmp)); + +    if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp))) +        return 0; + +    if (!MD5_Final(md5tmp, &mctx->md5)) +        return 0; + +    if (!SHA1_Update(&mctx->sha1, padtmp, 40)) +        return 0; + +    if (!SHA1_Final(sha1tmp, &mctx->sha1)) +        return 0; + +    /* Reinitialise context */ + +    if (!init(ctx)) +        return 0; + +    if (update(ctx, ms, mslen) <= 0) +        return 0; + +    /* Set padtmp to pad_2 value */ +    memset(padtmp, 0x5c, sizeof(padtmp)); + +    if (!MD5_Update(&mctx->md5, padtmp, sizeof(padtmp))) +        return 0; + +    if (!MD5_Update(&mctx->md5, md5tmp, sizeof(md5tmp))) +        return 0; + +    if (!SHA1_Update(&mctx->sha1, padtmp, 40)) +        return 0; + +    if (!SHA1_Update(&mctx->sha1, sha1tmp, sizeof(sha1tmp))) +        return 0; + +    /* Now when ctx is finalised it will return the SSL v3 hash value */ + +    OPENSSL_cleanse(md5tmp, sizeof(md5tmp)); +    OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp)); + +    return 1; + +} + +static const EVP_MD md5_sha1_md = { +    NID_md5_sha1, +    NID_md5_sha1, +    MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    MD5_CBLOCK, +    sizeof(EVP_MD *) + sizeof(struct md5_sha1_ctx), +    ctrl +}; + +const EVP_MD *EVP_md5_sha1(void) +{ +    return &md5_sha1_md; +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_mdc2.c b/openssl-1.1.0h/crypto/evp/m_mdc2.c new file mode 100644 index 0000000..b7f0fd8 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_mdc2.c @@ -0,0 +1,55 @@ +/* + * 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" + +#ifndef OPENSSL_NO_MDC2 + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/mdc2.h> +# include <openssl/rsa.h> +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return MDC2_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return MDC2_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return MDC2_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD mdc2_md = { +    NID_mdc2, +    NID_mdc2WithRSA, +    MDC2_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    MDC2_BLOCK, +    sizeof(EVP_MD *) + sizeof(MDC2_CTX), +}; + +const EVP_MD *EVP_mdc2(void) +{ +    return (&mdc2_md); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_null.c b/openssl-1.1.0h/crypto/evp/m_null.c new file mode 100644 index 0000000..6c4daf5 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_null.c @@ -0,0 +1,49 @@ +/* + * 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> +#include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return 1; +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return 1; +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return 1; +} + +static const EVP_MD null_md = { +    NID_undef, +    NID_undef, +    0, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    0, +    sizeof(EVP_MD *), +}; + +const EVP_MD *EVP_md_null(void) +{ +    return (&null_md); +} diff --git a/openssl-1.1.0h/crypto/evp/m_ripemd.c b/openssl-1.1.0h/crypto/evp/m_ripemd.c new file mode 100644 index 0000000..07b46bd --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_ripemd.c @@ -0,0 +1,55 @@ +/* + * 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" + +#ifndef OPENSSL_NO_RMD160 + +# include <openssl/ripemd.h> +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/rsa.h> +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return RIPEMD160_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return RIPEMD160_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return RIPEMD160_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD ripemd160_md = { +    NID_ripemd160, +    NID_ripemd160WithRSA, +    RIPEMD160_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    RIPEMD160_CBLOCK, +    sizeof(EVP_MD *) + sizeof(RIPEMD160_CTX), +}; + +const EVP_MD *EVP_ripemd160(void) +{ +    return (&ripemd160_md); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/m_sha1.c b/openssl-1.1.0h/crypto/evp/m_sha1.c new file mode 100644 index 0000000..e68f32a --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_sha1.c @@ -0,0 +1,248 @@ +/* + * 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 "internal/cryptlib.h" + +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/sha.h> +#include <openssl/rsa.h> +#include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return SHA1_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return SHA1_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return SHA1_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int ctrl(EVP_MD_CTX *ctx, int cmd, int mslen, void *ms) +{ +    unsigned char padtmp[40]; +    unsigned char sha1tmp[SHA_DIGEST_LENGTH]; + +    SHA_CTX *sha1; + +    if (cmd != EVP_CTRL_SSL3_MASTER_SECRET) +        return -2; + +    if (ctx == NULL) +        return 0; + +    sha1 = EVP_MD_CTX_md_data(ctx); + +    /* SSLv3 client auth handling: see RFC-6101 5.6.8 */ +    if (mslen != 48) +        return 0; + +    /* At this point hash contains all handshake messages, update +     * with master secret and pad_1. +     */ + +    if (SHA1_Update(sha1, ms, mslen) <= 0) +        return 0; + +    /* Set padtmp to pad_1 value */ +    memset(padtmp, 0x36, sizeof(padtmp)); + +    if (!SHA1_Update(sha1, padtmp, sizeof(padtmp))) +        return 0; + +    if (!SHA1_Final(sha1tmp, sha1)) +        return 0; + +    /* Reinitialise context */ + +    if (!SHA1_Init(sha1)) +        return 0; + +    if (SHA1_Update(sha1, ms, mslen) <= 0) +        return 0; + +    /* Set padtmp to pad_2 value */ +    memset(padtmp, 0x5c, sizeof(padtmp)); + +    if (!SHA1_Update(sha1, padtmp, sizeof(padtmp))) +        return 0; + +    if (!SHA1_Update(sha1, sha1tmp, sizeof(sha1tmp))) +        return 0; + +    /* Now when ctx is finalised it will return the SSL v3 hash value */ +    OPENSSL_cleanse(sha1tmp, sizeof(sha1tmp)); + +    return 1; + +} + +static const EVP_MD sha1_md = { +    NID_sha1, +    NID_sha1WithRSAEncryption, +    SHA_DIGEST_LENGTH, +    EVP_MD_FLAG_DIGALGID_ABSENT, +    init, +    update, +    final, +    NULL, +    NULL, +    SHA_CBLOCK, +    sizeof(EVP_MD *) + sizeof(SHA_CTX), +    ctrl +}; + +const EVP_MD *EVP_sha1(void) +{ +    return (&sha1_md); +} + +static int init224(EVP_MD_CTX *ctx) +{ +    return SHA224_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update224(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return SHA224_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final224(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return SHA224_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int init256(EVP_MD_CTX *ctx) +{ +    return SHA256_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update256(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return SHA256_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final256(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return SHA256_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD sha224_md = { +    NID_sha224, +    NID_sha224WithRSAEncryption, +    SHA224_DIGEST_LENGTH, +    EVP_MD_FLAG_DIGALGID_ABSENT, +    init224, +    update224, +    final224, +    NULL, +    NULL, +    SHA256_CBLOCK, +    sizeof(EVP_MD *) + sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha224(void) +{ +    return (&sha224_md); +} + +static const EVP_MD sha256_md = { +    NID_sha256, +    NID_sha256WithRSAEncryption, +    SHA256_DIGEST_LENGTH, +    EVP_MD_FLAG_DIGALGID_ABSENT, +    init256, +    update256, +    final256, +    NULL, +    NULL, +    SHA256_CBLOCK, +    sizeof(EVP_MD *) + sizeof(SHA256_CTX), +}; + +const EVP_MD *EVP_sha256(void) +{ +    return (&sha256_md); +} + +static int init384(EVP_MD_CTX *ctx) +{ +    return SHA384_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update384(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return SHA384_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final384(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return SHA384_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static int init512(EVP_MD_CTX *ctx) +{ +    return SHA512_Init(EVP_MD_CTX_md_data(ctx)); +} + +/* See comment in SHA224/256 section */ +static int update512(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return SHA512_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final512(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return SHA512_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD sha384_md = { +    NID_sha384, +    NID_sha384WithRSAEncryption, +    SHA384_DIGEST_LENGTH, +    EVP_MD_FLAG_DIGALGID_ABSENT, +    init384, +    update384, +    final384, +    NULL, +    NULL, +    SHA512_CBLOCK, +    sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha384(void) +{ +    return (&sha384_md); +} + +static const EVP_MD sha512_md = { +    NID_sha512, +    NID_sha512WithRSAEncryption, +    SHA512_DIGEST_LENGTH, +    EVP_MD_FLAG_DIGALGID_ABSENT, +    init512, +    update512, +    final512, +    NULL, +    NULL, +    SHA512_CBLOCK, +    sizeof(EVP_MD *) + sizeof(SHA512_CTX), +}; + +const EVP_MD *EVP_sha512(void) +{ +    return (&sha512_md); +} diff --git a/openssl-1.1.0h/crypto/evp/m_sigver.c b/openssl-1.1.0h/crypto/evp/m_sigver.c new file mode 100644 index 0000000..582e563 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_sigver.c @@ -0,0 +1,177 @@ +/* + * 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 + */ + +#include <stdio.h> +#include "internal/cryptlib.h" +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/x509.h> +#include "internal/evp_int.h" +#include "evp_locl.h" + +static int do_sigver_init(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, +                          const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey, +                          int ver) +{ +    if (ctx->pctx == NULL) +        ctx->pctx = EVP_PKEY_CTX_new(pkey, e); +    if (ctx->pctx == NULL) +        return 0; + +    if (!(ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM)) { + +        if (type == NULL) { +            int def_nid; +            if (EVP_PKEY_get_default_digest_nid(pkey, &def_nid) > 0) +                type = EVP_get_digestbynid(def_nid); +        } + +        if (type == NULL) { +            EVPerr(EVP_F_DO_SIGVER_INIT, EVP_R_NO_DEFAULT_DIGEST); +            return 0; +        } +    } + +    if (ver) { +        if (ctx->pctx->pmeth->verifyctx_init) { +            if (ctx->pctx->pmeth->verifyctx_init(ctx->pctx, ctx) <= 0) +                return 0; +            ctx->pctx->operation = EVP_PKEY_OP_VERIFYCTX; +        } else if (EVP_PKEY_verify_init(ctx->pctx) <= 0) +            return 0; +    } else { +        if (ctx->pctx->pmeth->signctx_init) { +            if (ctx->pctx->pmeth->signctx_init(ctx->pctx, ctx) <= 0) +                return 0; +            ctx->pctx->operation = EVP_PKEY_OP_SIGNCTX; +        } else if (EVP_PKEY_sign_init(ctx->pctx) <= 0) +            return 0; +    } +    if (EVP_PKEY_CTX_set_signature_md(ctx->pctx, type) <= 0) +        return 0; +    if (pctx) +        *pctx = ctx->pctx; +    if (ctx->pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) +        return 1; +    if (!EVP_DigestInit_ex(ctx, type, e)) +        return 0; +    return 1; +} + +int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, +                       const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) +{ +    return do_sigver_init(ctx, pctx, type, e, pkey, 0); +} + +int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx, +                         const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey) +{ +    return do_sigver_init(ctx, pctx, type, e, pkey, 1); +} + +int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, +                        size_t *siglen) +{ +    int sctx = 0, r = 0; +    EVP_PKEY_CTX *pctx = ctx->pctx; +    if (pctx->pmeth->flags & EVP_PKEY_FLAG_SIGCTX_CUSTOM) { +        if (!sigret) +            return pctx->pmeth->signctx(pctx, sigret, siglen, ctx); +        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) +            r = pctx->pmeth->signctx(pctx, sigret, siglen, ctx); +        else { +            EVP_PKEY_CTX *dctx = EVP_PKEY_CTX_dup(ctx->pctx); +            if (!dctx) +                return 0; +            r = dctx->pmeth->signctx(dctx, sigret, siglen, ctx); +            EVP_PKEY_CTX_free(dctx); +        } +        return r; +    } +    if (pctx->pmeth->signctx) +        sctx = 1; +    else +        sctx = 0; +    if (sigret) { +        unsigned char md[EVP_MAX_MD_SIZE]; +        unsigned int mdlen = 0; +        if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { +            if (sctx) +                r = ctx->pctx->pmeth->signctx(ctx->pctx, sigret, siglen, ctx); +            else +                r = EVP_DigestFinal_ex(ctx, md, &mdlen); +        } else { +            EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); +            if (tmp_ctx == NULL) +                return 0; +            if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { +                EVP_MD_CTX_free(tmp_ctx); +                return 0; +            } +            if (sctx) +                r = tmp_ctx->pctx->pmeth->signctx(tmp_ctx->pctx, +                                                  sigret, siglen, tmp_ctx); +            else +                r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); +            EVP_MD_CTX_free(tmp_ctx); +        } +        if (sctx || !r) +            return r; +        if (EVP_PKEY_sign(ctx->pctx, sigret, siglen, md, mdlen) <= 0) +            return 0; +    } else { +        if (sctx) { +            if (pctx->pmeth->signctx(pctx, sigret, siglen, ctx) <= 0) +                return 0; +        } else { +            int s = EVP_MD_size(ctx->digest); +            if (s < 0 || EVP_PKEY_sign(pctx, sigret, siglen, NULL, s) <= 0) +                return 0; +        } +    } +    return 1; +} + +int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig, +                          size_t siglen) +{ +    unsigned char md[EVP_MAX_MD_SIZE]; +    int r = 0; +    unsigned int mdlen = 0; +    int vctx = 0; + +    if (ctx->pctx->pmeth->verifyctx) +        vctx = 1; +    else +        vctx = 0; +    if (ctx->flags & EVP_MD_CTX_FLAG_FINALISE) { +        if (vctx) { +            r = ctx->pctx->pmeth->verifyctx(ctx->pctx, sig, siglen, ctx); +        } else +            r = EVP_DigestFinal_ex(ctx, md, &mdlen); +    } else { +        EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); +        if (tmp_ctx == NULL) +            return -1; +        if (!EVP_MD_CTX_copy_ex(tmp_ctx, ctx)) { +            EVP_MD_CTX_free(tmp_ctx); +            return -1; +        } +        if (vctx) { +            r = tmp_ctx->pctx->pmeth->verifyctx(tmp_ctx->pctx, +                                                sig, siglen, tmp_ctx); +        } else +            r = EVP_DigestFinal_ex(tmp_ctx, md, &mdlen); +        EVP_MD_CTX_free(tmp_ctx); +    } +    if (vctx || !r) +        return r; +    return EVP_PKEY_verify(ctx->pctx, sig, siglen, md, mdlen); +} diff --git a/openssl-1.1.0h/crypto/evp/m_wp.c b/openssl-1.1.0h/crypto/evp/m_wp.c new file mode 100644 index 0000000..94fac22 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/m_wp.c @@ -0,0 +1,54 @@ +/* + * Copyright 2005-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" + +#ifndef OPENSSL_NO_WHIRLPOOL + +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/whrlpool.h> +# include "internal/evp_int.h" + +static int init(EVP_MD_CTX *ctx) +{ +    return WHIRLPOOL_Init(EVP_MD_CTX_md_data(ctx)); +} + +static int update(EVP_MD_CTX *ctx, const void *data, size_t count) +{ +    return WHIRLPOOL_Update(EVP_MD_CTX_md_data(ctx), data, count); +} + +static int final(EVP_MD_CTX *ctx, unsigned char *md) +{ +    return WHIRLPOOL_Final(md, EVP_MD_CTX_md_data(ctx)); +} + +static const EVP_MD whirlpool_md = { +    NID_whirlpool, +    0, +    WHIRLPOOL_DIGEST_LENGTH, +    0, +    init, +    update, +    final, +    NULL, +    NULL, +    WHIRLPOOL_BBLOCK / 8, +    sizeof(EVP_MD *) + sizeof(WHIRLPOOL_CTX), +}; + +const EVP_MD *EVP_whirlpool(void) +{ +    return (&whirlpool_md); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/names.c b/openssl-1.1.0h/crypto/evp/names.c new file mode 100644 index 0000000..a92be1f --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/names.c @@ -0,0 +1,178 @@ +/* + * 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 <internal/objects.h> +#include <openssl/x509.h> +#include "internal/evp_int.h" + +int EVP_add_cipher(const EVP_CIPHER *c) +{ +    int r; + +    if (c == NULL) +        return 0; + +    r = OBJ_NAME_add(OBJ_nid2sn(c->nid), OBJ_NAME_TYPE_CIPHER_METH, +                     (const char *)c); +    if (r == 0) +        return (0); +    r = OBJ_NAME_add(OBJ_nid2ln(c->nid), OBJ_NAME_TYPE_CIPHER_METH, +                     (const char *)c); +    return (r); +} + +int EVP_add_digest(const EVP_MD *md) +{ +    int r; +    const char *name; + +    name = OBJ_nid2sn(md->type); +    r = OBJ_NAME_add(name, OBJ_NAME_TYPE_MD_METH, (const char *)md); +    if (r == 0) +        return (0); +    r = OBJ_NAME_add(OBJ_nid2ln(md->type), OBJ_NAME_TYPE_MD_METH, +                     (const char *)md); +    if (r == 0) +        return (0); + +    if (md->pkey_type && md->type != md->pkey_type) { +        r = OBJ_NAME_add(OBJ_nid2sn(md->pkey_type), +                         OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name); +        if (r == 0) +            return (0); +        r = OBJ_NAME_add(OBJ_nid2ln(md->pkey_type), +                         OBJ_NAME_TYPE_MD_METH | OBJ_NAME_ALIAS, name); +    } +    return (r); +} + +const EVP_CIPHER *EVP_get_cipherbyname(const char *name) +{ +    const EVP_CIPHER *cp; + +    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL)) +        return NULL; + +    cp = (const EVP_CIPHER *)OBJ_NAME_get(name, OBJ_NAME_TYPE_CIPHER_METH); +    return (cp); +} + +const EVP_MD *EVP_get_digestbyname(const char *name) +{ +    const EVP_MD *cp; + +    if (!OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)) +        return NULL; + +    cp = (const EVP_MD *)OBJ_NAME_get(name, OBJ_NAME_TYPE_MD_METH); +    return (cp); +} + +void evp_cleanup_int(void) +{ +    OBJ_NAME_cleanup(OBJ_NAME_TYPE_CIPHER_METH); +    OBJ_NAME_cleanup(OBJ_NAME_TYPE_MD_METH); +    /* +     * The above calls will only clean out the contents of the name hash +     * table, but not the hash table itself.  The following line does that +     * part.  -- Richard Levitte +     */ +    OBJ_NAME_cleanup(-1); + +    EVP_PBE_cleanup(); +    OBJ_sigid_free(); +} + +struct doall_cipher { +    void *arg; +    void (*fn) (const EVP_CIPHER *ciph, +                const char *from, const char *to, void *arg); +}; + +static void do_all_cipher_fn(const OBJ_NAME *nm, void *arg) +{ +    struct doall_cipher *dc = arg; +    if (nm->alias) +        dc->fn(NULL, nm->name, nm->data, dc->arg); +    else +        dc->fn((const EVP_CIPHER *)nm->data, nm->name, NULL, dc->arg); +} + +void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph, +                                   const char *from, const char *to, void *x), +                       void *arg) +{ +    struct doall_cipher dc; + +    /* Ignore errors */ +    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); + +    dc.fn = fn; +    dc.arg = arg; +    OBJ_NAME_do_all(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); +} + +void EVP_CIPHER_do_all_sorted(void (*fn) (const EVP_CIPHER *ciph, +                                          const char *from, const char *to, +                                          void *x), void *arg) +{ +    struct doall_cipher dc; + +    /* Ignore errors */ +    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL); + +    dc.fn = fn; +    dc.arg = arg; +    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, do_all_cipher_fn, &dc); +} + +struct doall_md { +    void *arg; +    void (*fn) (const EVP_MD *ciph, +                const char *from, const char *to, void *arg); +}; + +static void do_all_md_fn(const OBJ_NAME *nm, void *arg) +{ +    struct doall_md *dc = arg; +    if (nm->alias) +        dc->fn(NULL, nm->name, nm->data, dc->arg); +    else +        dc->fn((const EVP_MD *)nm->data, nm->name, NULL, dc->arg); +} + +void EVP_MD_do_all(void (*fn) (const EVP_MD *md, +                               const char *from, const char *to, void *x), +                   void *arg) +{ +    struct doall_md dc; + +    /* Ignore errors */ +    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); + +    dc.fn = fn; +    dc.arg = arg; +    OBJ_NAME_do_all(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); +} + +void EVP_MD_do_all_sorted(void (*fn) (const EVP_MD *md, +                                      const char *from, const char *to, +                                      void *x), void *arg) +{ +    struct doall_md dc; + +    OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL); + +    dc.fn = fn; +    dc.arg = arg; +    OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, do_all_md_fn, &dc); +} diff --git a/openssl-1.1.0h/crypto/evp/p5_crpt.c b/openssl-1.1.0h/crypto/evp/p5_crpt.c new file mode 100644 index 0000000..7e55d0b --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p5_crpt.c @@ -0,0 +1,103 @@ +/* + * 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 "internal/cryptlib.h" +#include <openssl/x509.h> +#include <openssl/evp.h> + +/* + * Doesn't do anything now: Builtin PBE algorithms in static table. + */ + +void PKCS5_PBE_add(void) +{ +} + +int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *cctx, const char *pass, int passlen, +                       ASN1_TYPE *param, const EVP_CIPHER *cipher, +                       const EVP_MD *md, int en_de) +{ +    EVP_MD_CTX *ctx; +    unsigned char md_tmp[EVP_MAX_MD_SIZE]; +    unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; +    int i; +    PBEPARAM *pbe; +    int saltlen, iter; +    unsigned char *salt; +    int mdsize; +    int rv = 0; + +    /* Extract useful info from parameter */ +    if (param == NULL || param->type != V_ASN1_SEQUENCE || +        param->value.sequence == NULL) { +        EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); +        return 0; +    } + +    pbe = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBEPARAM), param); +    if (pbe == NULL) { +        EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); +        return 0; +    } + +    if (!pbe->iter) +        iter = 1; +    else +        iter = ASN1_INTEGER_get(pbe->iter); +    salt = pbe->salt->data; +    saltlen = pbe->salt->length; + +    if (!pass) +        passlen = 0; +    else if (passlen == -1) +        passlen = strlen(pass); + +    ctx = EVP_MD_CTX_new(); +    if (ctx == NULL) { +        EVPerr(EVP_F_PKCS5_PBE_KEYIVGEN, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    if (!EVP_DigestInit_ex(ctx, md, NULL)) +        goto err; +    if (!EVP_DigestUpdate(ctx, pass, passlen)) +        goto err; +    if (!EVP_DigestUpdate(ctx, salt, saltlen)) +        goto err; +    PBEPARAM_free(pbe); +    if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL)) +        goto err; +    mdsize = EVP_MD_size(md); +    if (mdsize < 0) +        return 0; +    for (i = 1; i < iter; i++) { +        if (!EVP_DigestInit_ex(ctx, md, NULL)) +            goto err; +        if (!EVP_DigestUpdate(ctx, md_tmp, mdsize)) +            goto err; +        if (!EVP_DigestFinal_ex(ctx, md_tmp, NULL)) +            goto err; +    } +    OPENSSL_assert(EVP_CIPHER_key_length(cipher) <= (int)sizeof(md_tmp)); +    memcpy(key, md_tmp, EVP_CIPHER_key_length(cipher)); +    OPENSSL_assert(EVP_CIPHER_iv_length(cipher) <= 16); +    memcpy(iv, md_tmp + (16 - EVP_CIPHER_iv_length(cipher)), +           EVP_CIPHER_iv_length(cipher)); +    if (!EVP_CipherInit_ex(cctx, cipher, NULL, key, iv, en_de)) +        goto err; +    OPENSSL_cleanse(md_tmp, EVP_MAX_MD_SIZE); +    OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); +    OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH); +    rv = 1; + err: +    EVP_MD_CTX_free(ctx); +    return rv; +} diff --git a/openssl-1.1.0h/crypto/evp/p5_crpt2.c b/openssl-1.1.0h/crypto/evp/p5_crpt2.c new file mode 100644 index 0000000..6d5f289 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p5_crpt2.c @@ -0,0 +1,280 @@ +/* + * 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 "internal/cryptlib.h" +# include <openssl/x509.h> +# include <openssl/evp.h> +# include <openssl/hmac.h> +# include "evp_locl.h" + +/* set this to print out info about the keygen algorithm */ +/* #define OPENSSL_DEBUG_PKCS5V2 */ + +# ifdef OPENSSL_DEBUG_PKCS5V2 +static void h__dump(const unsigned char *p, int len); +# endif + +/* + * This is an implementation of PKCS#5 v2.0 password based encryption key + * derivation function PBKDF2. SHA1 version verified against test vectors + * posted by Peter Gutmann <pgut001@cs.auckland.ac.nz> to the PKCS-TNG + * <pkcs-tng@rsa.com> mailing list. + */ + +int PKCS5_PBKDF2_HMAC(const char *pass, int passlen, +                      const unsigned char *salt, int saltlen, int iter, +                      const EVP_MD *digest, int keylen, unsigned char *out) +{ +    const char *empty = ""; +    unsigned char digtmp[EVP_MAX_MD_SIZE], *p, itmp[4]; +    int cplen, j, k, tkeylen, mdlen; +    unsigned long i = 1; +    HMAC_CTX *hctx_tpl = NULL, *hctx = NULL; + +    mdlen = EVP_MD_size(digest); +    if (mdlen < 0) +        return 0; + +    hctx_tpl = HMAC_CTX_new(); +    if (hctx_tpl == NULL) +        return 0; +    p = out; +    tkeylen = keylen; +    if (pass == NULL) { +        pass = empty; +        passlen = 0; +    } else if (passlen == -1) { +        passlen = strlen(pass); +    } +    if (!HMAC_Init_ex(hctx_tpl, pass, passlen, digest, NULL)) { +        HMAC_CTX_free(hctx_tpl); +        return 0; +    } +    hctx = HMAC_CTX_new(); +    if (hctx == NULL) { +        HMAC_CTX_free(hctx_tpl); +        return 0; +    } +    while (tkeylen) { +        if (tkeylen > mdlen) +            cplen = mdlen; +        else +            cplen = tkeylen; +        /* +         * We are unlikely to ever use more than 256 blocks (5120 bits!) but +         * just in case... +         */ +        itmp[0] = (unsigned char)((i >> 24) & 0xff); +        itmp[1] = (unsigned char)((i >> 16) & 0xff); +        itmp[2] = (unsigned char)((i >> 8) & 0xff); +        itmp[3] = (unsigned char)(i & 0xff); +        if (!HMAC_CTX_copy(hctx, hctx_tpl)) { +            HMAC_CTX_free(hctx); +            HMAC_CTX_free(hctx_tpl); +            return 0; +        } +        if (!HMAC_Update(hctx, salt, saltlen) +            || !HMAC_Update(hctx, itmp, 4) +            || !HMAC_Final(hctx, digtmp, NULL)) { +            HMAC_CTX_free(hctx); +            HMAC_CTX_free(hctx_tpl); +            return 0; +        } +        HMAC_CTX_reset(hctx); +        memcpy(p, digtmp, cplen); +        for (j = 1; j < iter; j++) { +            if (!HMAC_CTX_copy(hctx, hctx_tpl)) { +                HMAC_CTX_free(hctx); +                HMAC_CTX_free(hctx_tpl); +                return 0; +            } +            if (!HMAC_Update(hctx, digtmp, mdlen) +                || !HMAC_Final(hctx, digtmp, NULL)) { +                HMAC_CTX_free(hctx); +                HMAC_CTX_free(hctx_tpl); +                return 0; +            } +            HMAC_CTX_reset(hctx); +            for (k = 0; k < cplen; k++) +                p[k] ^= digtmp[k]; +        } +        tkeylen -= cplen; +        i++; +        p += cplen; +    } +    HMAC_CTX_free(hctx); +    HMAC_CTX_free(hctx_tpl); +# ifdef OPENSSL_DEBUG_PKCS5V2 +    fprintf(stderr, "Password:\n"); +    h__dump(pass, passlen); +    fprintf(stderr, "Salt:\n"); +    h__dump(salt, saltlen); +    fprintf(stderr, "Iteration count %d\n", iter); +    fprintf(stderr, "Key:\n"); +    h__dump(out, keylen); +# endif +    return 1; +} + +int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, +                           const unsigned char *salt, int saltlen, int iter, +                           int keylen, unsigned char *out) +{ +    return PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, EVP_sha1(), +                             keylen, out); +} + +# ifdef DO_TEST +main() +{ +    unsigned char out[4]; +    unsigned char salt[] = { 0x12, 0x34, 0x56, 0x78 }; +    PKCS5_PBKDF2_HMAC_SHA1("password", -1, salt, 4, 5, 4, out); +    fprintf(stderr, "Out %02X %02X %02X %02X\n", +            out[0], out[1], out[2], out[3]); +} + +# endif + +/* + * Now the key derivation function itself. This is a bit evil because it has + * to check the ASN1 parameters are valid: and there are quite a few of + * them... + */ + +int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen, +                          ASN1_TYPE *param, const EVP_CIPHER *c, +                          const EVP_MD *md, int en_de) +{ +    PBE2PARAM *pbe2 = NULL; +    const EVP_CIPHER *cipher; +    EVP_PBE_KEYGEN *kdf; + +    int rv = 0; + +    pbe2 = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBE2PARAM), param); +    if (pbe2 == NULL) { +        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_DECODE_ERROR); +        goto err; +    } + +    /* See if we recognise the key derivation function */ +    if (!EVP_PBE_find(EVP_PBE_TYPE_KDF, OBJ_obj2nid(pbe2->keyfunc->algorithm), +                        NULL, NULL, &kdf)) { +        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, +               EVP_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION); +        goto err; +    } + +    /* +     * lets see if we recognise the encryption algorithm. +     */ + +    cipher = EVP_get_cipherbyobj(pbe2->encryption->algorithm); + +    if (!cipher) { +        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_UNSUPPORTED_CIPHER); +        goto err; +    } + +    /* Fixup cipher based on AlgorithmIdentifier */ +    if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, en_de)) +        goto err; +    if (EVP_CIPHER_asn1_to_param(ctx, pbe2->encryption->parameter) < 0) { +        EVPerr(EVP_F_PKCS5_V2_PBE_KEYIVGEN, EVP_R_CIPHER_PARAMETER_ERROR); +        goto err; +    } +    rv = kdf(ctx, pass, passlen, pbe2->keyfunc->parameter, NULL, NULL, en_de); + err: +    PBE2PARAM_free(pbe2); +    return rv; +} + +int PKCS5_v2_PBKDF2_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]; +    int saltlen, iter; +    int rv = 0; +    unsigned int keylen = 0; +    int prf_nid, hmac_md_nid; +    PBKDF2PARAM *kdf = NULL; +    const EVP_MD *prfmd; + +    if (EVP_CIPHER_CTX_cipher(ctx) == NULL) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_NO_CIPHER_SET); +        goto err; +    } +    keylen = EVP_CIPHER_CTX_key_length(ctx); +    OPENSSL_assert(keylen <= sizeof(key)); + +    /* Decode parameter */ + +    kdf = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(PBKDF2PARAM), param); + +    if (kdf == NULL) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_DECODE_ERROR); +        goto err; +    } + +    keylen = EVP_CIPHER_CTX_key_length(ctx); + +    /* Now check the parameters of the kdf */ + +    if (kdf->keylength && (ASN1_INTEGER_get(kdf->keylength) != (int)keylen)) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_KEYLENGTH); +        goto err; +    } + +    if (kdf->prf) +        prf_nid = OBJ_obj2nid(kdf->prf->algorithm); +    else +        prf_nid = NID_hmacWithSHA1; + +    if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, prf_nid, NULL, &hmac_md_nid, 0)) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); +        goto err; +    } + +    prfmd = EVP_get_digestbynid(hmac_md_nid); +    if (prfmd == NULL) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_PRF); +        goto err; +    } + +    if (kdf->salt->type != V_ASN1_OCTET_STRING) { +        EVPerr(EVP_F_PKCS5_V2_PBKDF2_KEYIVGEN, EVP_R_UNSUPPORTED_SALT_TYPE); +        goto err; +    } + +    /* it seems that its all OK */ +    salt = kdf->salt->value.octet_string->data; +    saltlen = kdf->salt->value.octet_string->length; +    iter = ASN1_INTEGER_get(kdf->iter); +    if (!PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, iter, prfmd, +                           keylen, key)) +        goto err; +    rv = EVP_CipherInit_ex(ctx, NULL, NULL, key, NULL, en_de); + err: +    OPENSSL_cleanse(key, keylen); +    PBKDF2PARAM_free(kdf); +    return rv; +} + +# ifdef OPENSSL_DEBUG_PKCS5V2 +static void h__dump(const unsigned char *p, int len) +{ +    for (; len--; p++) +        fprintf(stderr, "%02X ", *p); +    fprintf(stderr, "\n"); +} +# endif diff --git a/openssl-1.1.0h/crypto/evp/p_dec.c b/openssl-1.1.0h/crypto/evp/p_dec.c new file mode 100644 index 0000000..6bec406 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_dec.c @@ -0,0 +1,36 @@ +/* + * 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/rsa.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +int EVP_PKEY_decrypt_old(unsigned char *key, const unsigned char *ek, int ekl, +                         EVP_PKEY *priv) +{ +    int ret = -1; + +#ifndef OPENSSL_NO_RSA +    if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) { +#endif +        EVPerr(EVP_F_EVP_PKEY_DECRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA +        goto err; +    } + +    ret = +        RSA_private_decrypt(ekl, ek, key, EVP_PKEY_get0_RSA(priv), +                            RSA_PKCS1_PADDING); + err: +#endif +    return (ret); +} diff --git a/openssl-1.1.0h/crypto/evp/p_enc.c b/openssl-1.1.0h/crypto/evp/p_enc.c new file mode 100644 index 0000000..3277fbb --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_enc.c @@ -0,0 +1,35 @@ +/* + * 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/rsa.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +int EVP_PKEY_encrypt_old(unsigned char *ek, const unsigned char *key, +                         int key_len, EVP_PKEY *pubk) +{ +    int ret = 0; + +#ifndef OPENSSL_NO_RSA +    if (EVP_PKEY_id(pubk) != EVP_PKEY_RSA) { +#endif +        EVPerr(EVP_F_EVP_PKEY_ENCRYPT_OLD, EVP_R_PUBLIC_KEY_NOT_RSA); +#ifndef OPENSSL_NO_RSA +        goto err; +    } +    ret = +        RSA_public_encrypt(key_len, key, ek, EVP_PKEY_get0_RSA(pubk), +                           RSA_PKCS1_PADDING); + err: +#endif +    return (ret); +} diff --git a/openssl-1.1.0h/crypto/evp/p_lib.c b/openssl-1.1.0h/crypto/evp/p_lib.c new file mode 100644 index 0000000..d7372aa --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_lib.c @@ -0,0 +1,506 @@ +/* + * 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/err.h> +#include <openssl/objects.h> +#include <openssl/evp.h> +#include <openssl/x509.h> +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/engine.h> + +#include "internal/asn1_int.h" +#include "internal/evp_int.h" + +static void EVP_PKEY_free_it(EVP_PKEY *x); + +int EVP_PKEY_bits(const EVP_PKEY *pkey) +{ +    if (pkey && pkey->ameth && pkey->ameth->pkey_bits) +        return pkey->ameth->pkey_bits(pkey); +    return 0; +} + +int EVP_PKEY_security_bits(const EVP_PKEY *pkey) +{ +    if (pkey == NULL) +        return 0; +    if (!pkey->ameth || !pkey->ameth->pkey_security_bits) +        return -2; +    return pkey->ameth->pkey_security_bits(pkey); +} + +int EVP_PKEY_size(EVP_PKEY *pkey) +{ +    if (pkey && pkey->ameth && pkey->ameth->pkey_size) +        return pkey->ameth->pkey_size(pkey); +    return 0; +} + +int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode) +{ +#ifndef OPENSSL_NO_DSA +    if (pkey->type == EVP_PKEY_DSA) { +        int ret = pkey->save_parameters; + +        if (mode >= 0) +            pkey->save_parameters = mode; +        return (ret); +    } +#endif +#ifndef OPENSSL_NO_EC +    if (pkey->type == EVP_PKEY_EC) { +        int ret = pkey->save_parameters; + +        if (mode >= 0) +            pkey->save_parameters = mode; +        return (ret); +    } +#endif +    return (0); +} + +int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) +{ +    if (to->type == EVP_PKEY_NONE) { +        if (EVP_PKEY_set_type(to, from->type) == 0) +            return 0; +    } else if (to->type != from->type) { +        EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES); +        goto err; +    } + +    if (EVP_PKEY_missing_parameters(from)) { +        EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS); +        goto err; +    } + +    if (!EVP_PKEY_missing_parameters(to)) { +        if (EVP_PKEY_cmp_parameters(to, from) == 1) +            return 1; +        EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS); +        return 0; +    } + +    if (from->ameth && from->ameth->param_copy) +        return from->ameth->param_copy(to, from); + err: +    return 0; +} + +int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey) +{ +    if (pkey->ameth && pkey->ameth->param_missing) +        return pkey->ameth->param_missing(pkey); +    return 0; +} + +int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) +{ +    if (a->type != b->type) +        return -1; +    if (a->ameth && a->ameth->param_cmp) +        return a->ameth->param_cmp(a, b); +    return -2; +} + +int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b) +{ +    if (a->type != b->type) +        return -1; + +    if (a->ameth) { +        int ret; +        /* Compare parameters if the algorithm has them */ +        if (a->ameth->param_cmp) { +            ret = a->ameth->param_cmp(a, b); +            if (ret <= 0) +                return ret; +        } + +        if (a->ameth->pub_cmp) +            return a->ameth->pub_cmp(a, b); +    } + +    return -2; +} + +EVP_PKEY *EVP_PKEY_new(void) +{ +    EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret)); + +    if (ret == NULL) { +        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); +        return NULL; +    } +    ret->type = EVP_PKEY_NONE; +    ret->save_type = EVP_PKEY_NONE; +    ret->references = 1; +    ret->save_parameters = 1; +    ret->lock = CRYPTO_THREAD_lock_new(); +    if (ret->lock == NULL) { +        EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE); +        OPENSSL_free(ret); +        return NULL; +    } +    return ret; +} + +int EVP_PKEY_up_ref(EVP_PKEY *pkey) +{ +    int i; + +    if (CRYPTO_atomic_add(&pkey->references, 1, &i, pkey->lock) <= 0) +        return 0; + +    REF_PRINT_COUNT("EVP_PKEY", pkey); +    REF_ASSERT_ISNT(i < 2); +    return ((i > 1) ? 1 : 0); +} + +/* + * Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey + * is NULL just return 1 or 0 if the algorithm exists. + */ + +static int pkey_set_type(EVP_PKEY *pkey, int type, const char *str, int len) +{ +    const EVP_PKEY_ASN1_METHOD *ameth; +    ENGINE *e = NULL; +    if (pkey) { +        if (pkey->pkey.ptr) +            EVP_PKEY_free_it(pkey); +        /* +         * If key type matches and a method exists then this lookup has +         * succeeded once so just indicate success. +         */ +        if ((type == pkey->save_type) && pkey->ameth) +            return 1; +#ifndef OPENSSL_NO_ENGINE +        /* If we have ENGINEs release them */ +        ENGINE_finish(pkey->engine); +        pkey->engine = NULL; +        ENGINE_finish(pkey->pmeth_engine); +        pkey->pmeth_engine = NULL; +#endif +    } +    if (str) +        ameth = EVP_PKEY_asn1_find_str(&e, str, len); +    else +        ameth = EVP_PKEY_asn1_find(&e, type); +#ifndef OPENSSL_NO_ENGINE +    if (pkey == NULL) +        ENGINE_finish(e); +#endif +    if (ameth == NULL) { +        EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM); +        return 0; +    } +    if (pkey) { +        pkey->ameth = ameth; +        pkey->engine = e; + +        pkey->type = pkey->ameth->pkey_id; +        pkey->save_type = type; +    } +    return 1; +} + +int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) +{ +    return pkey_set_type(pkey, type, NULL, -1); +} + +int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len) +{ +    return pkey_set_type(pkey, EVP_PKEY_NONE, str, len); +} +#ifndef OPENSSL_NO_ENGINE +int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e) +{ +    if (e != NULL) { +        if (!ENGINE_init(e)) { +            EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB); +            return 0; +        } +        if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) { +            ENGINE_finish(e); +            EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM); +            return 0; +        } +    } +    ENGINE_finish(pkey->pmeth_engine); +    pkey->pmeth_engine = e; +    return 1; +} +#endif +int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) +{ +    if (pkey == NULL || !EVP_PKEY_set_type(pkey, type)) +        return 0; +    pkey->pkey.ptr = key; +    return (key != NULL); +} + +void *EVP_PKEY_get0(const EVP_PKEY *pkey) +{ +    return pkey->pkey.ptr; +} + +const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len) +{ +    ASN1_OCTET_STRING *os = NULL; +    if (pkey->type != EVP_PKEY_HMAC) { +        EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY); +        return NULL; +    } +    os = EVP_PKEY_get0(pkey); +    *len = os->length; +    return os->data; +} + +#ifndef OPENSSL_NO_RSA +int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key) +{ +    int ret = EVP_PKEY_assign_RSA(pkey, key); +    if (ret) +        RSA_up_ref(key); +    return ret; +} + +RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) +{ +    if (pkey->type != EVP_PKEY_RSA) { +        EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY); +        return NULL; +    } +    return pkey->pkey.rsa; +} + +RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey) +{ +    RSA *ret = EVP_PKEY_get0_RSA(pkey); +    if (ret != NULL) +        RSA_up_ref(ret); +    return ret; +} +#endif + +#ifndef OPENSSL_NO_DSA +int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key) +{ +    int ret = EVP_PKEY_assign_DSA(pkey, key); +    if (ret) +        DSA_up_ref(key); +    return ret; +} + +DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey) +{ +    if (pkey->type != EVP_PKEY_DSA) { +        EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY); +        return NULL; +    } +    return pkey->pkey.dsa; +} + +DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey) +{ +    DSA *ret = EVP_PKEY_get0_DSA(pkey); +    if (ret != NULL) +        DSA_up_ref(ret); +    return ret; +} +#endif + +#ifndef OPENSSL_NO_EC + +int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key) +{ +    int ret = EVP_PKEY_assign_EC_KEY(pkey, key); +    if (ret) +        EC_KEY_up_ref(key); +    return ret; +} + +EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ +    if (pkey->type != EVP_PKEY_EC) { +        EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY); +        return NULL; +    } +    return pkey->pkey.ec; +} + +EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey) +{ +    EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey); +    if (ret != NULL) +        EC_KEY_up_ref(ret); +    return ret; +} +#endif + +#ifndef OPENSSL_NO_DH + +int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key) +{ +    int ret = EVP_PKEY_assign_DH(pkey, key); +    if (ret) +        DH_up_ref(key); +    return ret; +} + +DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey) +{ +    if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) { +        EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY); +        return NULL; +    } +    return pkey->pkey.dh; +} + +DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey) +{ +    DH *ret = EVP_PKEY_get0_DH(pkey); +    if (ret != NULL) +        DH_up_ref(ret); +    return ret; +} +#endif + +int EVP_PKEY_type(int type) +{ +    int ret; +    const EVP_PKEY_ASN1_METHOD *ameth; +    ENGINE *e; +    ameth = EVP_PKEY_asn1_find(&e, type); +    if (ameth) +        ret = ameth->pkey_id; +    else +        ret = NID_undef; +#ifndef OPENSSL_NO_ENGINE +    ENGINE_finish(e); +#endif +    return ret; +} + +int EVP_PKEY_id(const EVP_PKEY *pkey) +{ +    return pkey->type; +} + +int EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ +    return EVP_PKEY_type(pkey->type); +} + +void EVP_PKEY_free(EVP_PKEY *x) +{ +    int i; + +    if (x == NULL) +        return; + +    CRYPTO_atomic_add(&x->references, -1, &i, x->lock); +    REF_PRINT_COUNT("EVP_PKEY", x); +    if (i > 0) +        return; +    REF_ASSERT_ISNT(i < 0); +    EVP_PKEY_free_it(x); +    CRYPTO_THREAD_lock_free(x->lock); +    sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free); +    OPENSSL_free(x); +} + +static void EVP_PKEY_free_it(EVP_PKEY *x) +{ +    /* internal function; x is never NULL */ +    if (x->ameth && x->ameth->pkey_free) { +        x->ameth->pkey_free(x); +        x->pkey.ptr = NULL; +    } +#ifndef OPENSSL_NO_ENGINE +    ENGINE_finish(x->engine); +    x->engine = NULL; +    ENGINE_finish(x->pmeth_engine); +    x->pmeth_engine = NULL; +#endif +} + +static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent, +                     const char *kstr) +{ +    BIO_indent(out, indent, 128); +    BIO_printf(out, "%s algorithm \"%s\" unsupported\n", +               kstr, OBJ_nid2ln(pkey->type)); +    return 1; +} + +int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, +                          int indent, ASN1_PCTX *pctx) +{ +    if (pkey->ameth && pkey->ameth->pub_print) +        return pkey->ameth->pub_print(out, pkey, indent, pctx); + +    return unsup_alg(out, pkey, indent, "Public Key"); +} + +int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, +                           int indent, ASN1_PCTX *pctx) +{ +    if (pkey->ameth && pkey->ameth->priv_print) +        return pkey->ameth->priv_print(out, pkey, indent, pctx); + +    return unsup_alg(out, pkey, indent, "Private Key"); +} + +int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, +                          int indent, ASN1_PCTX *pctx) +{ +    if (pkey->ameth && pkey->ameth->param_print) +        return pkey->ameth->param_print(out, pkey, indent, pctx); +    return unsup_alg(out, pkey, indent, "Parameters"); +} + +static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2) +{ +    if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL) +        return -2; +    return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2); +} + +int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid) +{ +    return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid); +} + +int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey, +                               const unsigned char *pt, size_t ptlen) +{ +    if (ptlen > INT_MAX) +        return 0; +    if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen, +                           (void *)pt) <= 0) +        return 0; +    return 1; +} + +size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt) +{ +    int rv; +    rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt); +    if (rv <= 0) +        return 0; +    return rv; +} diff --git a/openssl-1.1.0h/crypto/evp/p_open.c b/openssl-1.1.0h/crypto/evp/p_open.c new file mode 100644 index 0000000..b65bc74 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_open.c @@ -0,0 +1,73 @@ +/* + * 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 "internal/cryptlib.h" +#ifdef OPENSSL_NO_RSA +NON_EMPTY_TRANSLATION_UNIT +#else + +# include <stdio.h> +# include <openssl/evp.h> +# include <openssl/objects.h> +# include <openssl/x509.h> +# include <openssl/rsa.h> + +int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, +                 const unsigned char *ek, int ekl, const unsigned char *iv, +                 EVP_PKEY *priv) +{ +    unsigned char *key = NULL; +    int i, size = 0, ret = 0; + +    if (type) { +        EVP_CIPHER_CTX_reset(ctx); +        if (!EVP_DecryptInit_ex(ctx, type, NULL, NULL, NULL)) +            return 0; +    } + +    if (!priv) +        return 1; + +    if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) { +        EVPerr(EVP_F_EVP_OPENINIT, EVP_R_PUBLIC_KEY_NOT_RSA); +        goto err; +    } + +    size = EVP_PKEY_size(priv); +    key = OPENSSL_malloc(size + 2); +    if (key == NULL) { +        /* ERROR */ +        EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE); +        goto err; +    } + +    i = EVP_PKEY_decrypt_old(key, ek, ekl, priv); +    if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) { +        /* ERROR */ +        goto err; +    } +    if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) +        goto err; + +    ret = 1; + err: +    OPENSSL_clear_free(key, size); +    return (ret); +} + +int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int i; + +    i = EVP_DecryptFinal_ex(ctx, out, outl); +    if (i) +        i = EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL); +    return (i); +} +#endif diff --git a/openssl-1.1.0h/crypto/evp/p_seal.c b/openssl-1.1.0h/crypto/evp/p_seal.c new file mode 100644 index 0000000..faa2464 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_seal.c @@ -0,0 +1,70 @@ +/* + * 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/rand.h> +#include <openssl/rsa.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/x509.h> + +int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, +                 unsigned char **ek, int *ekl, unsigned char *iv, +                 EVP_PKEY **pubk, int npubk) +{ +    unsigned char key[EVP_MAX_KEY_LENGTH]; +    int i; + +    if (type) { +        EVP_CIPHER_CTX_reset(ctx); +        if (!EVP_EncryptInit_ex(ctx, type, NULL, NULL, NULL)) +            return 0; +    } +    if ((npubk <= 0) || !pubk) +        return 1; +    if (EVP_CIPHER_CTX_rand_key(ctx, key) <= 0) +        return 0; +    if (EVP_CIPHER_CTX_iv_length(ctx) +        && RAND_bytes(iv, EVP_CIPHER_CTX_iv_length(ctx)) <= 0) +        return 0; + +    if (!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) +        return 0; + +    for (i = 0; i < npubk; i++) { +        ekl[i] = +            EVP_PKEY_encrypt_old(ek[i], key, EVP_CIPHER_CTX_key_length(ctx), +                                 pubk[i]); +        if (ekl[i] <= 0) +            return (-1); +    } +    return (npubk); +} + +/*- MACRO +void EVP_SealUpdate(ctx,out,outl,in,inl) +EVP_CIPHER_CTX *ctx; +unsigned char *out; +int *outl; +unsigned char *in; +int inl; +        { +        EVP_EncryptUpdate(ctx,out,outl,in,inl); +        } +*/ + +int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) +{ +    int i; +    i = EVP_EncryptFinal_ex(ctx, out, outl); +    if (i) +        i = EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, NULL); +    return i; +} diff --git a/openssl-1.1.0h/crypto/evp/p_sign.c b/openssl-1.1.0h/crypto/evp/p_sign.c new file mode 100644 index 0000000..6cb442e --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_sign.c @@ -0,0 +1,61 @@ +/* + * 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> +#include "internal/evp_int.h" + +int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret, +                  unsigned int *siglen, EVP_PKEY *pkey) +{ +    unsigned char m[EVP_MAX_MD_SIZE]; +    unsigned int m_len = 0; +    int i = 0; +    size_t sltmp; +    EVP_PKEY_CTX *pkctx = NULL; + +    *siglen = 0; +    if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_FINALISE)) { +        if (!EVP_DigestFinal_ex(ctx, m, &m_len)) +            goto err; +    } else { +        int rv = 0; +        EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); +        if (tmp_ctx == NULL) { +            EVPerr(EVP_F_EVP_SIGNFINAL, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); +        if (rv) +            rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); +        EVP_MD_CTX_free(tmp_ctx); +        if (!rv) +            return 0; +    } + +    sltmp = (size_t)EVP_PKEY_size(pkey); +    i = 0; +    pkctx = EVP_PKEY_CTX_new(pkey, NULL); +    if (pkctx == NULL) +        goto err; +    if (EVP_PKEY_sign_init(pkctx) <= 0) +        goto err; +    if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0) +        goto err; +    if (EVP_PKEY_sign(pkctx, sigret, &sltmp, m, m_len) <= 0) +        goto err; +    *siglen = sltmp; +    i = 1; + err: +    EVP_PKEY_CTX_free(pkctx); +    return i; +} diff --git a/openssl-1.1.0h/crypto/evp/p_verify.c b/openssl-1.1.0h/crypto/evp/p_verify.c new file mode 100644 index 0000000..6e8c565 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/p_verify.c @@ -0,0 +1,55 @@ +/* + * 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> +#include "internal/evp_int.h" + +int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf, +                    unsigned int siglen, EVP_PKEY *pkey) +{ +    unsigned char m[EVP_MAX_MD_SIZE]; +    unsigned int m_len = 0; +    int i = 0; +    EVP_PKEY_CTX *pkctx = NULL; + +    if (EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_FINALISE)) { +        if (!EVP_DigestFinal_ex(ctx, m, &m_len)) +            goto err; +    } else { +        int rv = 0; +        EVP_MD_CTX *tmp_ctx = EVP_MD_CTX_new(); +        if (tmp_ctx == NULL) { +            EVPerr(EVP_F_EVP_VERIFYFINAL, ERR_R_MALLOC_FAILURE); +            return 0; +        } +        rv = EVP_MD_CTX_copy_ex(tmp_ctx, ctx); +        if (rv) +            rv = EVP_DigestFinal_ex(tmp_ctx, m, &m_len); +        EVP_MD_CTX_free(tmp_ctx); +        if (!rv) +            return 0; +    } + +    i = -1; +    pkctx = EVP_PKEY_CTX_new(pkey, NULL); +    if (pkctx == NULL) +        goto err; +    if (EVP_PKEY_verify_init(pkctx) <= 0) +        goto err; +    if (EVP_PKEY_CTX_set_signature_md(pkctx, EVP_MD_CTX_md(ctx)) <= 0) +        goto err; +    i = EVP_PKEY_verify(pkctx, sigbuf, siglen, m, m_len); + err: +    EVP_PKEY_CTX_free(pkctx); +    return i; +} diff --git a/openssl-1.1.0h/crypto/evp/pmeth_fn.c b/openssl-1.1.0h/crypto/evp/pmeth_fn.c new file mode 100644 index 0000000..eb63801 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/pmeth_fn.c @@ -0,0 +1,297 @@ +/* + * 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 + */ + +#include <stdio.h> +#include <stdlib.h> +#include "internal/cryptlib.h" +#include <openssl/objects.h> +#include <openssl/evp.h> +#include "internal/evp_int.h" + +#define M_check_autoarg(ctx, arg, arglen, err) \ +    if (ctx->pmeth->flags & EVP_PKEY_FLAG_AUTOARGLEN) {           \ +        size_t pksize = (size_t)EVP_PKEY_size(ctx->pkey);         \ +                                                                  \ +        if (pksize == 0) {                                        \ +            EVPerr(err, EVP_R_INVALID_KEY); /*ckerr_ignore*/      \ +            return 0;                                             \ +        }                                                         \ +        if (!arg) {                                               \ +            *arglen = pksize;                                     \ +            return 1;                                             \ +        }                                                         \ +        if (*arglen < pksize) {                                   \ +            EVPerr(err, EVP_R_BUFFER_TOO_SMALL); /*ckerr_ignore*/ \ +            return 0;                                             \ +        }                                                         \ +    } + +int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { +        EVPerr(EVP_F_EVP_PKEY_SIGN_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_SIGN; +    if (!ctx->pmeth->sign_init) +        return 1; +    ret = ctx->pmeth->sign_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_sign(EVP_PKEY_CTX *ctx, +                  unsigned char *sig, size_t *siglen, +                  const unsigned char *tbs, size_t tbslen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->sign) { +        EVPerr(EVP_F_EVP_PKEY_SIGN, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_SIGN) { +        EVPerr(EVP_F_EVP_PKEY_SIGN, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    M_check_autoarg(ctx, sig, siglen, EVP_F_EVP_PKEY_SIGN) +        return ctx->pmeth->sign(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_VERIFY; +    if (!ctx->pmeth->verify_init) +        return 1; +    ret = ctx->pmeth->verify_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, +                    const unsigned char *sig, size_t siglen, +                    const unsigned char *tbs, size_t tbslen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_VERIFY) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    return ctx->pmeth->verify(ctx, sig, siglen, tbs, tbslen); +} + +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_VERIFYRECOVER; +    if (!ctx->pmeth->verify_recover_init) +        return 1; +    ret = ctx->pmeth->verify_recover_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, +                            unsigned char *rout, size_t *routlen, +                            const unsigned char *sig, size_t siglen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) { +        EVPerr(EVP_F_EVP_PKEY_VERIFY_RECOVER, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    M_check_autoarg(ctx, rout, routlen, EVP_F_EVP_PKEY_VERIFY_RECOVER) +        return ctx->pmeth->verify_recover(ctx, rout, routlen, sig, siglen); +} + +int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { +        EVPerr(EVP_F_EVP_PKEY_ENCRYPT_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_ENCRYPT; +    if (!ctx->pmeth->encrypt_init) +        return 1; +    ret = ctx->pmeth->encrypt_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx, +                     unsigned char *out, size_t *outlen, +                     const unsigned char *in, size_t inlen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->encrypt) { +        EVPerr(EVP_F_EVP_PKEY_ENCRYPT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_ENCRYPT) { +        EVPerr(EVP_F_EVP_PKEY_ENCRYPT, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_ENCRYPT) +        return ctx->pmeth->encrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { +        EVPerr(EVP_F_EVP_PKEY_DECRYPT_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_DECRYPT; +    if (!ctx->pmeth->decrypt_init) +        return 1; +    ret = ctx->pmeth->decrypt_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx, +                     unsigned char *out, size_t *outlen, +                     const unsigned char *in, size_t inlen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->decrypt) { +        EVPerr(EVP_F_EVP_PKEY_DECRYPT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_DECRYPT) { +        EVPerr(EVP_F_EVP_PKEY_DECRYPT, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    M_check_autoarg(ctx, out, outlen, EVP_F_EVP_PKEY_DECRYPT) +        return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen); +} + +int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_DERIVE; +    if (!ctx->pmeth->derive_init) +        return 1; +    ret = ctx->pmeth->derive_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer) +{ +    int ret; +    if (!ctx || !ctx->pmeth +        || !(ctx->pmeth->derive || ctx->pmeth->encrypt || ctx->pmeth->decrypt) +        || !ctx->pmeth->ctrl) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_DERIVE +        && ctx->operation != EVP_PKEY_OP_ENCRYPT +        && ctx->operation != EVP_PKEY_OP_DECRYPT) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, +               EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } + +    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer); + +    if (ret <= 0) +        return ret; + +    if (ret == 2) +        return 1; + +    if (!ctx->pkey) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET); +        return -1; +    } + +    if (ctx->pkey->type != peer->type) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_KEY_TYPES); +        return -1; +    } + +    /* +     * ran@cryptocom.ru: For clarity.  The error is if parameters in peer are +     * present (!missing) but don't match.  EVP_PKEY_cmp_parameters may return +     * 1 (match), 0 (don't match) and -2 (comparison is not defined).  -1 +     * (different key types) is impossible here because it is checked earlier. +     * -2 is OK for us here, as well as 1, so we can check for 0 only. +     */ +    if (!EVP_PKEY_missing_parameters(peer) && +        !EVP_PKEY_cmp_parameters(ctx->pkey, peer)) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS); +        return -1; +    } + +    EVP_PKEY_free(ctx->peerkey); +    ctx->peerkey = peer; + +    ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer); + +    if (ret <= 0) { +        ctx->peerkey = NULL; +        return ret; +    } + +    EVP_PKEY_up_ref(peer); +    return 1; +} + +int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *pkeylen) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_DERIVE) { +        EVPerr(EVP_F_EVP_PKEY_DERIVE, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } +    M_check_autoarg(ctx, key, pkeylen, EVP_F_EVP_PKEY_DERIVE) +        return ctx->pmeth->derive(ctx, key, pkeylen); +} diff --git a/openssl-1.1.0h/crypto/evp/pmeth_gn.c b/openssl-1.1.0h/crypto/evp/pmeth_gn.c new file mode 100644 index 0000000..6adc3a9 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/pmeth_gn.c @@ -0,0 +1,169 @@ +/* + * 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 + */ + +#include <stdio.h> +#include <stdlib.h> +#include "internal/cryptlib.h" +#include <openssl/objects.h> +#include <openssl/evp.h> +#include "internal/bn_int.h" +#include "internal/evp_int.h" + +int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { +        EVPerr(EVP_F_EVP_PKEY_PARAMGEN_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_PARAMGEN; +    if (!ctx->pmeth->paramgen_init) +        return 1; +    ret = ctx->pmeth->paramgen_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->paramgen) { +        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } + +    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) { +        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } + +    if (ppkey == NULL) +        return -1; + +    if (*ppkey == NULL) +        *ppkey = EVP_PKEY_new(); + +    if (*ppkey == NULL) { +        EVPerr(EVP_F_EVP_PKEY_PARAMGEN, ERR_R_MALLOC_FAILURE); +        return -1; +    } + +    ret = ctx->pmeth->paramgen(ctx, *ppkey); +    if (ret <= 0) { +        EVP_PKEY_free(*ppkey); +        *ppkey = NULL; +    } +    return ret; +} + +int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { +        EVPerr(EVP_F_EVP_PKEY_KEYGEN_INIT, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    ctx->operation = EVP_PKEY_OP_KEYGEN; +    if (!ctx->pmeth->keygen_init) +        return 1; +    ret = ctx->pmeth->keygen_init(ctx); +    if (ret <= 0) +        ctx->operation = EVP_PKEY_OP_UNDEFINED; +    return ret; +} + +int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey) +{ +    int ret; + +    if (!ctx || !ctx->pmeth || !ctx->pmeth->keygen) { +        EVPerr(EVP_F_EVP_PKEY_KEYGEN, +               EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE); +        return -2; +    } +    if (ctx->operation != EVP_PKEY_OP_KEYGEN) { +        EVPerr(EVP_F_EVP_PKEY_KEYGEN, EVP_R_OPERATON_NOT_INITIALIZED); +        return -1; +    } + +    if (ppkey == NULL) +        return -1; + +    if (*ppkey == NULL) +        *ppkey = EVP_PKEY_new(); +    if (*ppkey == NULL) +        return -1; + +    ret = ctx->pmeth->keygen(ctx, *ppkey); +    if (ret <= 0) { +        EVP_PKEY_free(*ppkey); +        *ppkey = NULL; +    } +    return ret; +} + +void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb) +{ +    ctx->pkey_gencb = cb; +} + +EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx) +{ +    return ctx->pkey_gencb; +} + +/* + * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style + * callbacks. + */ + +static int trans_cb(int a, int b, BN_GENCB *gcb) +{ +    EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb); +    ctx->keygen_info[0] = a; +    ctx->keygen_info[1] = b; +    return ctx->pkey_gencb(ctx); +} + +void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx) +{ +    BN_GENCB_set(cb, trans_cb, ctx); +} + +int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx) +{ +    if (idx == -1) +        return ctx->keygen_info_count; +    if (idx < 0 || idx > ctx->keygen_info_count) +        return 0; +    return ctx->keygen_info[idx]; +} + +EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e, +                               const unsigned char *key, int keylen) +{ +    EVP_PKEY_CTX *mac_ctx = NULL; +    EVP_PKEY *mac_key = NULL; +    mac_ctx = EVP_PKEY_CTX_new_id(type, e); +    if (!mac_ctx) +        return NULL; +    if (EVP_PKEY_keygen_init(mac_ctx) <= 0) +        goto merr; +    if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0) +        goto merr; +    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0) +        goto merr; + merr: +    EVP_PKEY_CTX_free(mac_ctx); +    return mac_key; +} diff --git a/openssl-1.1.0h/crypto/evp/pmeth_lib.c b/openssl-1.1.0h/crypto/evp/pmeth_lib.c new file mode 100644 index 0000000..5e650a9 --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/pmeth_lib.c @@ -0,0 +1,725 @@ +/* + * 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 + */ + +#include <stdio.h> +#include <stdlib.h> +#include "internal/cryptlib.h" +#include <openssl/engine.h> +#include <openssl/evp.h> +#include <openssl/x509v3.h> +#include "internal/asn1_int.h" +#include "internal/evp_int.h" +#include "internal/numbers.h" + +typedef int sk_cmp_fn_type(const char *const *a, const char *const *b); + +static STACK_OF(EVP_PKEY_METHOD) *app_pkey_methods = NULL; + +static const EVP_PKEY_METHOD *standard_methods[] = { +#ifndef OPENSSL_NO_RSA +    &rsa_pkey_meth, +#endif +#ifndef OPENSSL_NO_DH +    &dh_pkey_meth, +#endif +#ifndef OPENSSL_NO_DSA +    &dsa_pkey_meth, +#endif +#ifndef OPENSSL_NO_EC +    &ec_pkey_meth, +#endif +    &hmac_pkey_meth, +#ifndef OPENSSL_NO_CMAC +    &cmac_pkey_meth, +#endif +#ifndef OPENSSL_NO_DH +    &dhx_pkey_meth, +#endif +    &tls1_prf_pkey_meth, +#ifndef OPENSSL_NO_EC +    &ecx25519_pkey_meth, +#endif +    &hkdf_pkey_meth +}; + +DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, +                           pmeth); + +static int pmeth_cmp(const EVP_PKEY_METHOD *const *a, +                     const EVP_PKEY_METHOD *const *b) +{ +    return ((*a)->pkey_id - (*b)->pkey_id); +} + +IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_METHOD *, const EVP_PKEY_METHOD *, +                             pmeth); + +const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type) +{ +    EVP_PKEY_METHOD tmp; +    const EVP_PKEY_METHOD *t = &tmp, **ret; +    tmp.pkey_id = type; +    if (app_pkey_methods) { +        int idx; +        idx = sk_EVP_PKEY_METHOD_find(app_pkey_methods, &tmp); +        if (idx >= 0) +            return sk_EVP_PKEY_METHOD_value(app_pkey_methods, idx); +    } +    ret = OBJ_bsearch_pmeth(&t, standard_methods, +                            sizeof(standard_methods) / +                            sizeof(EVP_PKEY_METHOD *)); +    if (!ret || !*ret) +        return NULL; +    return *ret; +} + +static EVP_PKEY_CTX *int_ctx_new(EVP_PKEY *pkey, ENGINE *e, int id) +{ +    EVP_PKEY_CTX *ret; +    const EVP_PKEY_METHOD *pmeth; +    if (id == -1) { +        if (!pkey || !pkey->ameth) +            return NULL; +        id = pkey->ameth->pkey_id; +    } +#ifndef OPENSSL_NO_ENGINE +    if (e == NULL && pkey != NULL) +        e = pkey->pmeth_engine != NULL ? pkey->pmeth_engine : pkey->engine; +    /* Try to find an ENGINE which implements this method */ +    if (e) { +        if (!ENGINE_init(e)) { +            EVPerr(EVP_F_INT_CTX_NEW, ERR_R_ENGINE_LIB); +            return NULL; +        } +    } else { +        e = ENGINE_get_pkey_meth_engine(id); +    } + +    /* +     * If an ENGINE handled this method look it up. Otherwise use internal +     * tables. +     */ + +    if (e) +        pmeth = ENGINE_get_pkey_meth(e, id); +    else +#endif +        pmeth = EVP_PKEY_meth_find(id); + +    if (pmeth == NULL) { +#ifndef OPENSSL_NO_ENGINE +        ENGINE_finish(e); +#endif +        EVPerr(EVP_F_INT_CTX_NEW, EVP_R_UNSUPPORTED_ALGORITHM); +        return NULL; +    } + +    ret = OPENSSL_zalloc(sizeof(*ret)); +    if (ret == NULL) { +#ifndef OPENSSL_NO_ENGINE +        ENGINE_finish(e); +#endif +        EVPerr(EVP_F_INT_CTX_NEW, ERR_R_MALLOC_FAILURE); +        return NULL; +    } +    ret->engine = e; +    ret->pmeth = pmeth; +    ret->operation = EVP_PKEY_OP_UNDEFINED; +    ret->pkey = pkey; +    if (pkey) +        EVP_PKEY_up_ref(pkey); + +    if (pmeth->init) { +        if (pmeth->init(ret) <= 0) { +            ret->pmeth = NULL; +            EVP_PKEY_CTX_free(ret); +            return NULL; +        } +    } + +    return ret; +} + +EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags) +{ +    EVP_PKEY_METHOD *pmeth; + +    pmeth = OPENSSL_zalloc(sizeof(*pmeth)); +    if (pmeth == NULL) +        return NULL; + +    pmeth->pkey_id = id; +    pmeth->flags = flags | EVP_PKEY_FLAG_DYNAMIC; +    return pmeth; +} + +void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags, +                             const EVP_PKEY_METHOD *meth) +{ +    if (ppkey_id) +        *ppkey_id = meth->pkey_id; +    if (pflags) +        *pflags = meth->flags; +} + +void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src) +{ + +    dst->init = src->init; +    dst->copy = src->copy; +    dst->cleanup = src->cleanup; + +    dst->paramgen_init = src->paramgen_init; +    dst->paramgen = src->paramgen; + +    dst->keygen_init = src->keygen_init; +    dst->keygen = src->keygen; + +    dst->sign_init = src->sign_init; +    dst->sign = src->sign; + +    dst->verify_init = src->verify_init; +    dst->verify = src->verify; + +    dst->verify_recover_init = src->verify_recover_init; +    dst->verify_recover = src->verify_recover; + +    dst->signctx_init = src->signctx_init; +    dst->signctx = src->signctx; + +    dst->verifyctx_init = src->verifyctx_init; +    dst->verifyctx = src->verifyctx; + +    dst->encrypt_init = src->encrypt_init; +    dst->encrypt = src->encrypt; + +    dst->decrypt_init = src->decrypt_init; +    dst->decrypt = src->decrypt; + +    dst->derive_init = src->derive_init; +    dst->derive = src->derive; + +    dst->ctrl = src->ctrl; +    dst->ctrl_str = src->ctrl_str; +} + +void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth) +{ +    if (pmeth && (pmeth->flags & EVP_PKEY_FLAG_DYNAMIC)) +        OPENSSL_free(pmeth); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e) +{ +    return int_ctx_new(pkey, e, -1); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e) +{ +    return int_ctx_new(NULL, e, id); +} + +EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) +{ +    EVP_PKEY_CTX *rctx; +    if (!pctx->pmeth || !pctx->pmeth->copy) +        return NULL; +#ifndef OPENSSL_NO_ENGINE +    /* Make sure it's safe to copy a pkey context using an ENGINE */ +    if (pctx->engine && !ENGINE_init(pctx->engine)) { +        EVPerr(EVP_F_EVP_PKEY_CTX_DUP, ERR_R_ENGINE_LIB); +        return 0; +    } +#endif +    rctx = OPENSSL_malloc(sizeof(*rctx)); +    if (rctx == NULL) +        return NULL; + +    rctx->pmeth = pctx->pmeth; +#ifndef OPENSSL_NO_ENGINE +    rctx->engine = pctx->engine; +#endif + +    if (pctx->pkey) +        EVP_PKEY_up_ref(pctx->pkey); + +    rctx->pkey = pctx->pkey; + +    if (pctx->peerkey) +        EVP_PKEY_up_ref(pctx->peerkey); + +    rctx->peerkey = pctx->peerkey; + +    rctx->data = NULL; +    rctx->app_data = NULL; +    rctx->operation = pctx->operation; + +    if (pctx->pmeth->copy(rctx, pctx) > 0) +        return rctx; + +    rctx->pmeth = NULL; +    EVP_PKEY_CTX_free(rctx); +    return NULL; + +} + +int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth) +{ +    if (app_pkey_methods == NULL) { +        app_pkey_methods = sk_EVP_PKEY_METHOD_new(pmeth_cmp); +        if (app_pkey_methods == NULL) +            return 0; +    } +    if (!sk_EVP_PKEY_METHOD_push(app_pkey_methods, pmeth)) +        return 0; +    sk_EVP_PKEY_METHOD_sort(app_pkey_methods); +    return 1; +} + +void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx) +{ +    if (ctx == NULL) +        return; +    if (ctx->pmeth && ctx->pmeth->cleanup) +        ctx->pmeth->cleanup(ctx); +    EVP_PKEY_free(ctx->pkey); +    EVP_PKEY_free(ctx->peerkey); +#ifndef OPENSSL_NO_ENGINE +    ENGINE_finish(ctx->engine); +#endif +    OPENSSL_free(ctx); +} + +int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, +                      int cmd, int p1, void *p2) +{ +    int ret; +    if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) { +        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); +        return -2; +    } +    if ((keytype != -1) && (ctx->pmeth->pkey_id != keytype)) +        return -1; + +    if (ctx->operation == EVP_PKEY_OP_UNDEFINED) { +        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_NO_OPERATION_SET); +        return -1; +    } + +    if ((optype != -1) && !(ctx->operation & optype)) { +        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_INVALID_OPERATION); +        return -1; +    } + +    ret = ctx->pmeth->ctrl(ctx, cmd, p1, p2); + +    if (ret == -2) +        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED); + +    return ret; + +} + +int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, +                          const char *name, const char *value) +{ +    if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl_str) { +        EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_COMMAND_NOT_SUPPORTED); +        return -2; +    } +    if (strcmp(name, "digest") == 0) { +        const EVP_MD *md; +        if (value == NULL || (md = EVP_get_digestbyname(value)) == NULL) { +            EVPerr(EVP_F_EVP_PKEY_CTX_CTRL_STR, EVP_R_INVALID_DIGEST); +            return 0; +        } +        return EVP_PKEY_CTX_set_signature_md(ctx, md); +    } +    return ctx->pmeth->ctrl_str(ctx, name, value); +} + +/* Utility functions to send a string of hex string to a ctrl */ + +int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str) +{ +    size_t len; + +    len = strlen(str); +    if (len > INT_MAX) +        return -1; +    return ctx->pmeth->ctrl(ctx, cmd, len, (void *)str); +} + +int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex) +{ +    unsigned char *bin; +    long binlen; +    int rv = -1; + +    bin = OPENSSL_hexstr2buf(hex, &binlen); +    if (bin == NULL) +        return 0; +    if (binlen <= INT_MAX) +        rv = ctx->pmeth->ctrl(ctx, cmd, binlen, bin); +    OPENSSL_free(bin); +    return rv; +} + +int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx) +{ +    return ctx->operation; +} + +void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen) +{ +    ctx->keygen_info = dat; +    ctx->keygen_info_count = datlen; +} + +void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data) +{ +    ctx->data = data; +} + +void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx) +{ +    return ctx->data; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) +{ +    return ctx->pkey; +} + +EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx) +{ +    return ctx->peerkey; +} + +void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) +{ +    ctx->app_data = data; +} + +void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) +{ +    return ctx->app_data; +} + +void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth, +                            int (*init) (EVP_PKEY_CTX *ctx)) +{ +    pmeth->init = init; +} + +void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth, +                            int (*copy) (EVP_PKEY_CTX *dst, +                                         EVP_PKEY_CTX *src)) +{ +    pmeth->copy = copy; +} + +void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth, +                               void (*cleanup) (EVP_PKEY_CTX *ctx)) +{ +    pmeth->cleanup = cleanup; +} + +void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth, +                                int (*paramgen_init) (EVP_PKEY_CTX *ctx), +                                int (*paramgen) (EVP_PKEY_CTX *ctx, +                                                 EVP_PKEY *pkey)) +{ +    pmeth->paramgen_init = paramgen_init; +    pmeth->paramgen = paramgen; +} + +void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth, +                              int (*keygen_init) (EVP_PKEY_CTX *ctx), +                              int (*keygen) (EVP_PKEY_CTX *ctx, +                                             EVP_PKEY *pkey)) +{ +    pmeth->keygen_init = keygen_init; +    pmeth->keygen = keygen; +} + +void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth, +                            int (*sign_init) (EVP_PKEY_CTX *ctx), +                            int (*sign) (EVP_PKEY_CTX *ctx, +                                         unsigned char *sig, size_t *siglen, +                                         const unsigned char *tbs, +                                         size_t tbslen)) +{ +    pmeth->sign_init = sign_init; +    pmeth->sign = sign; +} + +void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth, +                              int (*verify_init) (EVP_PKEY_CTX *ctx), +                              int (*verify) (EVP_PKEY_CTX *ctx, +                                             const unsigned char *sig, +                                             size_t siglen, +                                             const unsigned char *tbs, +                                             size_t tbslen)) +{ +    pmeth->verify_init = verify_init; +    pmeth->verify = verify; +} + +void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth, +                                      int (*verify_recover_init) (EVP_PKEY_CTX +                                                                  *ctx), +                                      int (*verify_recover) (EVP_PKEY_CTX +                                                             *ctx, +                                                             unsigned char +                                                             *sig, +                                                             size_t *siglen, +                                                             const unsigned +                                                             char *tbs, +                                                             size_t tbslen)) +{ +    pmeth->verify_recover_init = verify_recover_init; +    pmeth->verify_recover = verify_recover; +} + +void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth, +                               int (*signctx_init) (EVP_PKEY_CTX *ctx, +                                                    EVP_MD_CTX *mctx), +                               int (*signctx) (EVP_PKEY_CTX *ctx, +                                               unsigned char *sig, +                                               size_t *siglen, +                                               EVP_MD_CTX *mctx)) +{ +    pmeth->signctx_init = signctx_init; +    pmeth->signctx = signctx; +} + +void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth, +                                 int (*verifyctx_init) (EVP_PKEY_CTX *ctx, +                                                        EVP_MD_CTX *mctx), +                                 int (*verifyctx) (EVP_PKEY_CTX *ctx, +                                                   const unsigned char *sig, +                                                   int siglen, +                                                   EVP_MD_CTX *mctx)) +{ +    pmeth->verifyctx_init = verifyctx_init; +    pmeth->verifyctx = verifyctx; +} + +void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth, +                               int (*encrypt_init) (EVP_PKEY_CTX *ctx), +                               int (*encryptfn) (EVP_PKEY_CTX *ctx, +                                                 unsigned char *out, +                                                 size_t *outlen, +                                                 const unsigned char *in, +                                                 size_t inlen)) +{ +    pmeth->encrypt_init = encrypt_init; +    pmeth->encrypt = encryptfn; +} + +void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth, +                               int (*decrypt_init) (EVP_PKEY_CTX *ctx), +                               int (*decrypt) (EVP_PKEY_CTX *ctx, +                                               unsigned char *out, +                                               size_t *outlen, +                                               const unsigned char *in, +                                               size_t inlen)) +{ +    pmeth->decrypt_init = decrypt_init; +    pmeth->decrypt = decrypt; +} + +void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth, +                              int (*derive_init) (EVP_PKEY_CTX *ctx), +                              int (*derive) (EVP_PKEY_CTX *ctx, +                                             unsigned char *key, +                                             size_t *keylen)) +{ +    pmeth->derive_init = derive_init; +    pmeth->derive = derive; +} + +void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth, +                            int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, +                                         void *p2), +                            int (*ctrl_str) (EVP_PKEY_CTX *ctx, +                                             const char *type, +                                             const char *value)) +{ +    pmeth->ctrl = ctrl; +    pmeth->ctrl_str = ctrl_str; +} + +void EVP_PKEY_meth_get_init(EVP_PKEY_METHOD *pmeth, +                            int (**pinit) (EVP_PKEY_CTX *ctx)) +{ +    *pinit = pmeth->init; +} + +void EVP_PKEY_meth_get_copy(EVP_PKEY_METHOD *pmeth, +                            int (**pcopy) (EVP_PKEY_CTX *dst, +                                           EVP_PKEY_CTX *src)) +{ +    *pcopy = pmeth->copy; +} + +void EVP_PKEY_meth_get_cleanup(EVP_PKEY_METHOD *pmeth, +                               void (**pcleanup) (EVP_PKEY_CTX *ctx)) +{ +    *pcleanup = pmeth->cleanup; +} + +void EVP_PKEY_meth_get_paramgen(EVP_PKEY_METHOD *pmeth, +                                int (**pparamgen_init) (EVP_PKEY_CTX *ctx), +                                int (**pparamgen) (EVP_PKEY_CTX *ctx, +                                                   EVP_PKEY *pkey)) +{ +    if (pparamgen_init) +        *pparamgen_init = pmeth->paramgen_init; +    if (pparamgen) +        *pparamgen = pmeth->paramgen; +} + +void EVP_PKEY_meth_get_keygen(EVP_PKEY_METHOD *pmeth, +                              int (**pkeygen_init) (EVP_PKEY_CTX *ctx), +                              int (**pkeygen) (EVP_PKEY_CTX *ctx, +                                               EVP_PKEY *pkey)) +{ +    if (pkeygen_init) +        *pkeygen_init = pmeth->keygen_init; +    if (pkeygen) +        *pkeygen = pmeth->keygen; +} + +void EVP_PKEY_meth_get_sign(EVP_PKEY_METHOD *pmeth, +                            int (**psign_init) (EVP_PKEY_CTX *ctx), +                            int (**psign) (EVP_PKEY_CTX *ctx, +                                           unsigned char *sig, size_t *siglen, +                                           const unsigned char *tbs, +                                           size_t tbslen)) +{ +    if (psign_init) +        *psign_init = pmeth->sign_init; +    if (psign) +        *psign = pmeth->sign; +} + +void EVP_PKEY_meth_get_verify(EVP_PKEY_METHOD *pmeth, +                              int (**pverify_init) (EVP_PKEY_CTX *ctx), +                              int (**pverify) (EVP_PKEY_CTX *ctx, +                                               const unsigned char *sig, +                                               size_t siglen, +                                               const unsigned char *tbs, +                                               size_t tbslen)) +{ +    if (pverify_init) +        *pverify_init = pmeth->verify_init; +    if (pverify) +        *pverify = pmeth->verify; +} + +void EVP_PKEY_meth_get_verify_recover(EVP_PKEY_METHOD *pmeth, +                                      int (**pverify_recover_init) (EVP_PKEY_CTX +                                                                    *ctx), +                                      int (**pverify_recover) (EVP_PKEY_CTX +                                                               *ctx, +                                                               unsigned char +                                                               *sig, +                                                               size_t *siglen, +                                                               const unsigned +                                                               char *tbs, +                                                               size_t tbslen)) +{ +    if (pverify_recover_init) +        *pverify_recover_init = pmeth->verify_recover_init; +    if (pverify_recover) +        *pverify_recover = pmeth->verify_recover; +} + +void EVP_PKEY_meth_get_signctx(EVP_PKEY_METHOD *pmeth, +                               int (**psignctx_init) (EVP_PKEY_CTX *ctx, +                                                      EVP_MD_CTX *mctx), +                               int (**psignctx) (EVP_PKEY_CTX *ctx, +                                                 unsigned char *sig, +                                                 size_t *siglen, +                                                 EVP_MD_CTX *mctx)) +{ +    if (psignctx_init) +        *psignctx_init = pmeth->signctx_init; +    if (psignctx) +        *psignctx = pmeth->signctx; +} + +void EVP_PKEY_meth_get_verifyctx(EVP_PKEY_METHOD *pmeth, +                                 int (**pverifyctx_init) (EVP_PKEY_CTX *ctx, +                                                          EVP_MD_CTX *mctx), +                                 int (**pverifyctx) (EVP_PKEY_CTX *ctx, +                                                     const unsigned char *sig, +                                                     int siglen, +                                                     EVP_MD_CTX *mctx)) +{ +    if (pverifyctx_init) +        *pverifyctx_init = pmeth->verifyctx_init; +    if (pverifyctx) +        *pverifyctx = pmeth->verifyctx; +} + +void EVP_PKEY_meth_get_encrypt(EVP_PKEY_METHOD *pmeth, +                               int (**pencrypt_init) (EVP_PKEY_CTX *ctx), +                               int (**pencryptfn) (EVP_PKEY_CTX *ctx, +                                                   unsigned char *out, +                                                   size_t *outlen, +                                                   const unsigned char *in, +                                                   size_t inlen)) +{ +    if (pencrypt_init) +        *pencrypt_init = pmeth->encrypt_init; +    if (pencryptfn) +        *pencryptfn = pmeth->encrypt; +} + +void EVP_PKEY_meth_get_decrypt(EVP_PKEY_METHOD *pmeth, +                               int (**pdecrypt_init) (EVP_PKEY_CTX *ctx), +                               int (**pdecrypt) (EVP_PKEY_CTX *ctx, +                                                 unsigned char *out, +                                                 size_t *outlen, +                                                 const unsigned char *in, +                                                 size_t inlen)) +{ +    if (pdecrypt_init) +        *pdecrypt_init = pmeth->decrypt_init; +    if (pdecrypt) +        *pdecrypt = pmeth->decrypt; +} + +void EVP_PKEY_meth_get_derive(EVP_PKEY_METHOD *pmeth, +                              int (**pderive_init) (EVP_PKEY_CTX *ctx), +                              int (**pderive) (EVP_PKEY_CTX *ctx, +                                               unsigned char *key, +                                               size_t *keylen)) +{ +    if (pderive_init) +        *pderive_init = pmeth->derive_init; +    if (pderive) +        *pderive = pmeth->derive; +} + +void EVP_PKEY_meth_get_ctrl(EVP_PKEY_METHOD *pmeth, +                            int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1, +                                           void *p2), +                            int (**pctrl_str) (EVP_PKEY_CTX *ctx, +                                               const char *type, +                                               const char *value)) +{ +    if (pctrl) +        *pctrl = pmeth->ctrl; +    if (pctrl_str) +        *pctrl_str = pmeth->ctrl_str; +} diff --git a/openssl-1.1.0h/crypto/evp/scrypt.c b/openssl-1.1.0h/crypto/evp/scrypt.c new file mode 100644 index 0000000..101bb1e --- /dev/null +++ b/openssl-1.1.0h/crypto/evp/scrypt.c @@ -0,0 +1,248 @@ +/* + * 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 <stddef.h> +#include <stdio.h> +#include <string.h> +#include <openssl/evp.h> +#include <openssl/err.h> +#include <internal/numbers.h> + +#ifndef OPENSSL_NO_SCRYPT + +#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b)))) +static void salsa208_word_specification(uint32_t inout[16]) +{ +    int i; +    uint32_t x[16]; +    memcpy(x, inout, sizeof(x)); +    for (i = 8; i > 0; i -= 2) { +        x[4] ^= R(x[0] + x[12], 7); +        x[8] ^= R(x[4] + x[0], 9); +        x[12] ^= R(x[8] + x[4], 13); +        x[0] ^= R(x[12] + x[8], 18); +        x[9] ^= R(x[5] + x[1], 7); +        x[13] ^= R(x[9] + x[5], 9); +        x[1] ^= R(x[13] + x[9], 13); +        x[5] ^= R(x[1] + x[13], 18); +        x[14] ^= R(x[10] + x[6], 7); +        x[2] ^= R(x[14] + x[10], 9); +        x[6] ^= R(x[2] + x[14], 13); +        x[10] ^= R(x[6] + x[2], 18); +        x[3] ^= R(x[15] + x[11], 7); +        x[7] ^= R(x[3] + x[15], 9); +        x[11] ^= R(x[7] + x[3], 13); +        x[15] ^= R(x[11] + x[7], 18); +        x[1] ^= R(x[0] + x[3], 7); +        x[2] ^= R(x[1] + x[0], 9); +        x[3] ^= R(x[2] + x[1], 13); +        x[0] ^= R(x[3] + x[2], 18); +        x[6] ^= R(x[5] + x[4], 7); +        x[7] ^= R(x[6] + x[5], 9); +        x[4] ^= R(x[7] + x[6], 13); +        x[5] ^= R(x[4] + x[7], 18); +        x[11] ^= R(x[10] + x[9], 7); +        x[8] ^= R(x[11] + x[10], 9); +        x[9] ^= R(x[8] + x[11], 13); +        x[10] ^= R(x[9] + x[8], 18); +        x[12] ^= R(x[15] + x[14], 7); +        x[13] ^= R(x[12] + x[15], 9); +        x[14] ^= R(x[13] + x[12], 13); +        x[15] ^= R(x[14] + x[13], 18); +    } +    for (i = 0; i < 16; ++i) +        inout[i] += x[i]; +    OPENSSL_cleanse(x, sizeof(x)); +} + +static void scryptBlockMix(uint32_t *B_, uint32_t *B, uint64_t r) +{ +    uint64_t i, j; +    uint32_t X[16], *pB; + +    memcpy(X, B + (r * 2 - 1) * 16, sizeof(X)); +    pB = B; +    for (i = 0; i < r * 2; i++) { +        for (j = 0; j < 16; j++) +            X[j] ^= *pB++; +        salsa208_word_specification(X); +        memcpy(B_ + (i / 2 + (i & 1) * r) * 16, X, sizeof(X)); +    } +    OPENSSL_cleanse(X, sizeof(X)); +} + +static void scryptROMix(unsigned char *B, uint64_t r, uint64_t N, +                        uint32_t *X, uint32_t *T, uint32_t *V) +{ +    unsigned char *pB; +    uint32_t *pV; +    uint64_t i, k; + +    /* Convert from little endian input */ +    for (pV = V, i = 0, pB = B; i < 32 * r; i++, pV++) { +        *pV = *pB++; +        *pV |= *pB++ << 8; +        *pV |= *pB++ << 16; +        *pV |= (uint32_t)*pB++ << 24; +    } + +    for (i = 1; i < N; i++, pV += 32 * r) +        scryptBlockMix(pV, pV - 32 * r, r); + +    scryptBlockMix(X, V + (N - 1) * 32 * r, r); + +    for (i = 0; i < N; i++) { +        uint32_t j; +        j = X[16 * (2 * r - 1)] % N; +        pV = V + 32 * r * j; +        for (k = 0; k < 32 * r; k++) +            T[k] = X[k] ^ *pV++; +        scryptBlockMix(X, T, r); +    } +    /* Convert output to little endian */ +    for (i = 0, pB = B; i < 32 * r; i++) { +        uint32_t xtmp = X[i]; +        *pB++ = xtmp & 0xff; +        *pB++ = (xtmp >> 8) & 0xff; +        *pB++ = (xtmp >> 16) & 0xff; +        *pB++ = (xtmp >> 24) & 0xff; +    } +} + +#ifndef SIZE_MAX +# define SIZE_MAX    ((size_t)-1) +#endif + +/* + * Maximum power of two that will fit in uint64_t: this should work on + * most (all?) platforms. + */ + +#define LOG2_UINT64_MAX         (sizeof(uint64_t) * 8 - 1) + +/* + * Maximum value of p * r: + * p <= ((2^32-1) * hLen) / MFLen => + * p <= ((2^32-1) * 32) / (128 * r) => + * p * r <= (2^30-1) + * + */ + +#define SCRYPT_PR_MAX   ((1 << 30) - 1) + +/* + * Maximum permitted memory allow this to be overridden with Configuration + * option: e.g. -DSCRYPT_MAX_MEM=0 for maximum possible. + */ + +#ifdef SCRYPT_MAX_MEM +# if SCRYPT_MAX_MEM == 0 +#  undef SCRYPT_MAX_MEM +/* + * Although we could theoretically allocate SIZE_MAX memory that would leave + * no memory available for anything else so set limit as half that. + */ +#  define SCRYPT_MAX_MEM (SIZE_MAX/2) +# endif +#else +/* Default memory limit: 32 MB */ +# define SCRYPT_MAX_MEM  (1024 * 1024 * 32) +#endif + +int EVP_PBE_scrypt(const char *pass, size_t passlen, +                   const unsigned char *salt, size_t saltlen, +                   uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem, +                   unsigned char *key, size_t keylen) +{ +    int rv = 0; +    unsigned char *B; +    uint32_t *X, *V, *T; +    uint64_t i, Blen, Vlen; +    size_t allocsize; + +    /* Sanity check parameters */ +    /* initial check, r,p must be non zero, N >= 2 and a power of 2 */ +    if (r == 0 || p == 0 || N < 2 || (N & (N - 1))) +        return 0; +    /* Check p * r < SCRYPT_PR_MAX avoiding overflow */ +    if (p > SCRYPT_PR_MAX / r) +        return 0; + +    /* +     * Need to check N: if 2^(128 * r / 8) overflows limit this is +     * automatically satisfied since N <= UINT64_MAX. +     */ + +    if (16 * r <= LOG2_UINT64_MAX) { +        if (N >= (((uint64_t)1) << (16 * r))) +            return 0; +    } + +    /* Memory checks: check total allocated buffer size fits in uint64_t */ + +    /* +     * B size in section 5 step 1.S +     * Note: we know p * 128 * r < UINT64_MAX because we already checked +     * p * r < SCRYPT_PR_MAX +     */ +    Blen = p * 128 * r; + +    /* +     * Check 32 * r * (N + 2) * sizeof(uint32_t) fits in +     * uint64_t and also size_t (their sizes are unrelated). +     * This is combined size V, X and T (section 4) +     */ +    i = UINT64_MAX / (32 * sizeof(uint32_t)); +    if (N + 2 > i / r) +        return 0; +    Vlen = 32 * r * (N + 2) * sizeof(uint32_t); + +    /* check total allocated size fits in uint64_t */ +    if (Blen > UINT64_MAX - Vlen) +        return 0; +    /* check total allocated size fits in size_t */ +    if (Blen > SIZE_MAX - Vlen) +        return 0; + +    allocsize = (size_t)(Blen + Vlen); + +    if (maxmem == 0) +        maxmem = SCRYPT_MAX_MEM; + +    if (allocsize > maxmem) { +        EVPerr(EVP_F_EVP_PBE_SCRYPT, EVP_R_MEMORY_LIMIT_EXCEEDED); +        return 0; +    } + +    /* If no key return to indicate parameters are OK */ +    if (key == NULL) +        return 1; + +    B = OPENSSL_malloc(allocsize); +    if (B == NULL) +        return 0; +    X = (uint32_t *)(B + Blen); +    T = X + 32 * r; +    V = T + 32 * r; +    if (PKCS5_PBKDF2_HMAC(pass, passlen, salt, saltlen, 1, EVP_sha256(), +                          Blen, B) == 0) +        goto err; + +    for (i = 0; i < p; i++) +        scryptROMix(B + 128 * r * i, r, N, X, T, V); + +    if (PKCS5_PBKDF2_HMAC(pass, passlen, B, Blen, 1, EVP_sha256(), +                          keylen, key) == 0) +        goto err; +    rv = 1; + err: +    OPENSSL_clear_free(B, allocsize); +    return rv; +} +#endif  | 
