Commit c0804614 authored by Matt Caswell's avatar Matt Caswell
Browse files

Change SRP functions to use EVP_EncodeUpdate/EVP_DecodeUpdate functions



Previously they were using EVP_EncodeBlock/EVP_DecodeBlock. These are low
level functions that do not handle padding characters. This was causing
the SRP code to fail. One side effect of using EVP_EncodeUpdate is that
it inserts newlines which is not what we need in SRP so we add a flag to
avoid that.

Reviewed-by: default avatarAndy Polyakov <appro@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/5925)
parent 0320e8e2
Loading
Loading
Loading
Loading
+21 −7
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include "evp_locl.h"
#include "internal/evp_int.h"

static unsigned char conv_ascii2bin(unsigned char a);
#ifndef CHARSET_EBCDIC
@@ -115,11 +116,17 @@ int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx)
    return ctx->num;
}

void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags)
{
    ctx->flags = flags;
}

void EVP_EncodeInit(EVP_ENCODE_CTX *ctx)
{
    ctx->length = 48;
    ctx->num = 0;
    ctx->line_num = 0;
    ctx->flags = 0;
}

int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
@@ -145,18 +152,24 @@ int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
        j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
        ctx->num = 0;
        out += j;
        total = j;
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
            *(out++) = '\n';
            total++;
        }
        *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;
        total += j;
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0) {
            *(out++) = '\n';
            total++;
        }
        *out = '\0';
        total += j + 1;
    }
    if (total > INT_MAX) {
        /* Too much output data! */
@@ -177,6 +190,7 @@ void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl)

    if (ctx->num != 0) {
        ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
        if ((ctx->flags & EVP_ENCODE_CTX_NO_NEWLINES) == 0)
            out[ret++] = '\n';
        out[ret] = '\0';
        ctx->num = 0;
@@ -217,11 +231,11 @@ int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int dlen)

void EVP_DecodeInit(EVP_ENCODE_CTX *ctx)
{
    /* Only ctx->num is used during decoding. */
    /* Only ctx->num and ctx->flags are used during decoding. */
    ctx->num = 0;
    ctx->length = 0;
    ctx->line_num = 0;
    ctx->expect_nl = 0;
    ctx->flags = 0;
}

/*-
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ struct evp_Encode_Ctx_st {
    unsigned char enc_data[80];
    /* number read on current line */
    int line_num;
    int expect_nl;
    unsigned int flags;
};

typedef struct evp_pbe_st EVP_PBE_CTL;
+6 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
 * https://www.openssl.org/source/license.html
 */

#include <openssl/evp.h>
#include "internal/refcount.h"

struct evp_pkey_ctx_st {
@@ -422,3 +423,8 @@ void evp_app_cleanup_int(void);
#ifndef TLS1_1_VERSION
# define TLS1_1_VERSION   0x0302
#endif

void evp_encode_ctx_set_flags(EVP_ENCODE_CTX *ctx, unsigned int flags);

/* EVP_ENCODE_CTX flags */
#define EVP_ENCODE_CTX_NO_NEWLINES      1
+37 −5
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#ifndef OPENSSL_NO_SRP
# include "internal/cryptlib.h"
# include "internal/evp_int.h"
# include <openssl/sha.h>
# include <openssl/srp.h>
# include <openssl/evp.h>
@@ -26,24 +27,55 @@

/*
 * Convert a base64 string into raw byte array representation.
 * Returns the length of the decoded data, or -1 on error.
 */
static int t_fromb64(unsigned char *a, size_t alen, const char *src)
{
    EVP_ENCODE_CTX *ctx;
    int outl = 0, outl2 = 0;
    size_t size = strlen(src);

    /* Four bytes in src become three bytes output. */
    if (size > INT_MAX || (size / 4) * 3 > alen)
    if (size > INT_MAX)
        return -1;

    return EVP_DecodeBlock(a, (unsigned char *)src, (int)size);
    ctx = EVP_ENCODE_CTX_new();
    if (ctx == NULL)
        return -1;

    EVP_DecodeInit(ctx);
    if (EVP_DecodeUpdate(ctx, a, &outl, (const unsigned char *)src, size) < 0) {
        EVP_ENCODE_CTX_free(ctx);
        return -1;
    }
    EVP_DecodeFinal(ctx, a + outl, &outl2);

    EVP_ENCODE_CTX_free(ctx);
    return outl + outl2;
}

/*
 * Convert a raw byte string into a null-terminated base64 ASCII string.
 * Returns 1 on success or 0 on error.
 */
static void t_tob64(char *dst, const unsigned char *src, int size)
static int t_tob64(char *dst, const unsigned char *src, int size)
{
    EVP_EncodeBlock((unsigned char *)dst, src, size);
    EVP_ENCODE_CTX *ctx = EVP_ENCODE_CTX_new();
    int outl = 0, outl2 = 0;

    if (ctx == NULL)
        return 0;

    EVP_EncodeInit(ctx);
    evp_encode_ctx_set_flags(ctx, EVP_ENCODE_CTX_NO_NEWLINES);

    if (!EVP_EncodeUpdate(ctx, (unsigned char *)dst, &outl, src, size)) {
        EVP_ENCODE_CTX_free(ctx);
        return 0;
    }
    EVP_EncodeFinal(ctx, (unsigned char *)dst + outl, &outl2);

    EVP_ENCODE_CTX_free(ctx);
    return 1;
}

void SRP_user_pwd_free(SRP_user_pwd *user_pwd)