Commit 7fc7d1a7 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Add EC_KEY_priv2buf()



Add new function EC_KEY_priv2buf() to allocated and encode private
key octet in one call. Update and simplify ASN.1 and print routines.

Reviewed-by: default avatarViktor Dukhovni <viktor@openssl.org>
parent ac3e3665
Loading
Loading
Loading
Loading
+17 −46
Original line number Diff line number Diff line
@@ -387,51 +387,29 @@ typedef enum {

static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
{
    unsigned char *buffer = NULL;
    const char *ecstr;
    size_t priv_len = 0, pub_len = 0, buf_len = 0;
    int ret = 0, reason = ERR_R_BIO_LIB;
    BIGNUM *pub_key = NULL;
    BN_CTX *ctx = NULL;
    unsigned char *priv = NULL, *pub = NULL;
    size_t privlen = 0, publen = 0;
    int ret = 0;
    const EC_GROUP *group;
    const EC_POINT *public_key = NULL;

    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
        reason = ERR_R_PASSED_NULL_PARAMETER;
        goto err;
        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER);
        return 0;
    }

    if (ktype != EC_KEY_PRINT_PARAM) {
        public_key = EC_KEY_get0_public_key(x);
        if (public_key != NULL) {
            pub_len = EC_POINT_point2oct(group, public_key,
                                         EC_KEY_get_conv_form(x),
                                         NULL, 0, NULL);
            if (pub_len == 0) {
                reason = ERR_R_EC_LIB;
        publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
        if (publen == 0)
            goto err;
    }
            buf_len = pub_len;
        }
    }

    if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
        priv_len = EC_KEY_priv2oct(x, NULL, 0);
        if (priv_len == 0) {
            reason = ERR_R_EC_LIB;
        privlen = EC_KEY_priv2buf(x, &priv);
        if (privlen == 0)
            goto err;
    }
        if (priv_len > buf_len)
            buf_len = priv_len;
    }

    if (buf_len != 0) {
        buffer = OPENSSL_malloc(buf_len);
        if (buffer == NULL) {
            reason = ERR_R_MALLOC_FAILURE;
            goto err;
        }
    }
    if (ktype == EC_KEY_PRINT_PRIVATE)
        ecstr = "Private-Key";
    else if (ktype == EC_KEY_PRINT_PUBLIC)
@@ -445,23 +423,17 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
                   EC_GROUP_order_bits(group)) <= 0)
        goto err;

    if (priv_len != 0) {
    if (privlen != 0) {
        if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
            goto err;
        if (EC_KEY_priv2oct(x, buffer, priv_len) == 0)
            goto err;
        if (ASN1_buf_print(bp, buffer, priv_len, off + 4) == 0)
        if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
            goto err;
    }

    if (pub_len != 0) {
    if (publen != 0) {
        if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
            goto err;
        if (EC_POINT_point2oct(group, public_key,
                               EC_KEY_get_conv_form(x),
                               buffer, pub_len, NULL) == 0)
            goto err;
        if (ASN1_buf_print(bp, buffer, pub_len, off + 4) == 0)
        if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
            goto err;
    }

@@ -470,10 +442,9 @@ static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
    ret = 1;
 err:
    if (!ret)
        ECerr(EC_F_DO_EC_KEY_PRINT, reason);
    BN_free(pub_key);
    BN_CTX_free(ctx);
    OPENSSL_clear_free(buffer, buf_len);
        ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB);
    OPENSSL_clear_free(priv, privlen);
    OPENSSL_free(pub);
    return ret;
}

+13 −38
Original line number Diff line number Diff line
@@ -1075,8 +1075,9 @@ EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const unsigned char **in, long len)
int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
{
    int ret = 0, ok = 0;
    unsigned char *buffer = NULL;
    size_t buf_len = 0, tmp_len;
    unsigned char *priv= NULL, *pub= NULL;
    size_t privlen, publen;

    EC_PRIVATEKEY *priv_key = NULL;

    if (a == NULL || a->group == NULL ||
@@ -1092,28 +1093,15 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)

    priv_key->version = a->version;

    buf_len = EC_KEY_priv2oct(a, NULL, 0);
    privlen = EC_KEY_priv2buf(a, &priv);

    if (buf_len == 0) {
    if (privlen == 0) {
        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
        goto err;
    }

    buffer = OPENSSL_malloc(buf_len);
    if (buffer == NULL) {
        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
        goto err;
    }

    if (EC_KEY_priv2oct(a, buffer, buf_len) == 0) {
        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
        goto err;
    }

    if (!ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
        ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
        goto err;
    }
    ASN1_STRING_set0(priv_key->privateKey, priv, privlen);
    priv = NULL;

    if (!(a->enc_flag & EC_PKEY_NO_PARAMETERS)) {
        if ((priv_key->parameters =
@@ -1131,31 +1119,17 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
            goto err;
        }

        tmp_len = EC_POINT_point2oct(a->group, a->pub_key,
                                     a->conv_form, NULL, 0, NULL);

        if (tmp_len > buf_len) {
            unsigned char *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
            if (!tmp_buffer) {
                ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_MALLOC_FAILURE);
                goto err;
            }
            buffer = tmp_buffer;
            buf_len = tmp_len;
        }
        publen = EC_KEY_key2buf(a, a->conv_form, &pub, NULL);

        if (!EC_POINT_point2oct(a->group, a->pub_key,
                                a->conv_form, buffer, buf_len, NULL)) {
        if (publen == 0) {
            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_EC_LIB);
            goto err;
        }

        priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
        priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
        if (!ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
            ECerr(EC_F_I2D_ECPRIVATEKEY, ERR_R_ASN1_LIB);
            goto err;
        }
        ASN1_STRING_set0(priv_key->publicKey, pub, publen);
        pub = NULL;
    }

    if ((ret = i2d_EC_PRIVATEKEY(priv_key, out)) == 0) {
@@ -1164,7 +1138,8 @@ int i2d_ECPrivateKey(EC_KEY *a, unsigned char **out)
    }
    ok = 1;
 err:
    OPENSSL_free(buffer);
    OPENSSL_clear_free(priv, privlen);
    OPENSSL_free(pub);
    EC_PRIVATEKEY_free(priv_key);
    return (ok ? ret : 0);
}
+19 −0
Original line number Diff line number Diff line
@@ -591,3 +591,22 @@ int EC_KEY_oct2priv(EC_KEY *eckey, unsigned char *buf, size_t len)
    }
    return 1;
}

size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf)
{
    size_t len;
    unsigned char *buf;
    len = EC_KEY_priv2oct(eckey, NULL, 0);
    if (len == 0)
        return 0;
    buf = OPENSSL_malloc(len);
    if (buf == NULL)
        return 0;
    len = EC_KEY_priv2oct(eckey, buf, len);
    if (len == 0) {
        OPENSSL_free(buf);
        return 0;
    }
    *pbuf = buf;
    return len;
}
+7 −0
Original line number Diff line number Diff line
@@ -953,6 +953,13 @@ int EC_KEY_oct2priv(EC_KEY *key, unsigned char *buf, size_t len);

size_t EC_KEY_priv2oct(const EC_KEY *key, unsigned char *buf, size_t len);

/** Encodes an EC_KEY private key to an allocated octet string
 *  \param  key    key to encode
 *  \param  pbuf   returns pointer to allocated buffer
 *  \return the length of the encoded octet string or 0 if an error occurred
 */

size_t EC_KEY_priv2buf(const EC_KEY *eckey, unsigned char **pbuf);

/********************************************************************/
/*        de- and encoding functions for SEC1 ECPrivateKey          */