/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-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
#include <openssl/err.h>
#include <openssl/asn1t.h>
#include <openssl/objects.h>
+#include "internal/nelem.h"
int EC_GROUP_get_basis_type(const EC_GROUP *group)
{
- int i = 0;
+ int i;
if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
NID_X9_62_characteristic_two_field)
/* everything else is currently not supported */
return 0;
- while (group->poly[i] != 0)
- i++;
+ /* Find the last non-zero element of group->poly[] */
+ for (i = 0;
+ i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
+ i++)
+ continue;
if (i == 4)
return NID_X9_62_ppBasis;
/* some structures needed for the asn1 encoding */
typedef struct x9_62_pentanomial_st {
- long k1;
- long k2;
- long k3;
+ int32_t k1;
+ int32_t k2;
+ int32_t k3;
} X9_62_PENTANOMIAL;
typedef struct x9_62_characteristic_two_st {
- long m;
+ int32_t m;
ASN1_OBJECT *type;
union {
char *ptr;
} X9_62_CURVE;
struct ec_parameters_st {
- long version;
+ int32_t version;
X9_62_FIELDID *fieldID;
X9_62_CURVE *curve;
ASN1_OCTET_STRING *base;
/* SEC1 ECPrivateKey */
typedef struct ec_privatekey_st {
- long version;
+ int32_t version;
ASN1_OCTET_STRING *privateKey;
ECPKPARAMETERS *parameters;
ASN1_BIT_STRING *publicKey;
/* the OpenSSL ASN.1 definitions */
ASN1_SEQUENCE(X9_62_PENTANOMIAL) = {
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k1, LONG),
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k2, LONG),
- ASN1_SIMPLE(X9_62_PENTANOMIAL, k3, LONG)
+ ASN1_EMBED(X9_62_PENTANOMIAL, k1, INT32),
+ ASN1_EMBED(X9_62_PENTANOMIAL, k2, INT32),
+ ASN1_EMBED(X9_62_PENTANOMIAL, k3, INT32)
} static_ASN1_SEQUENCE_END(X9_62_PENTANOMIAL)
DECLARE_ASN1_ALLOC_FUNCTIONS(X9_62_PENTANOMIAL)
} ASN1_ADB_END(X9_62_CHARACTERISTIC_TWO, 0, type, 0, &char_two_def_tt, NULL);
ASN1_SEQUENCE(X9_62_CHARACTERISTIC_TWO) = {
- ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, m, LONG),
+ ASN1_EMBED(X9_62_CHARACTERISTIC_TWO, m, INT32),
ASN1_SIMPLE(X9_62_CHARACTERISTIC_TWO, type, ASN1_OBJECT),
ASN1_ADB_OBJECT(X9_62_CHARACTERISTIC_TWO)
} static_ASN1_SEQUENCE_END(X9_62_CHARACTERISTIC_TWO)
} static_ASN1_SEQUENCE_END(X9_62_CURVE)
ASN1_SEQUENCE(ECPARAMETERS) = {
- ASN1_SIMPLE(ECPARAMETERS, version, LONG),
+ ASN1_EMBED(ECPARAMETERS, version, INT32),
ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS)
ASN1_SEQUENCE(EC_PRIVATEKEY) = {
- ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
+ ASN1_EMBED(EC_PRIVATEKEY, version, INT32),
ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1)
err:
BN_free(tmp);
- return (ok);
+ return ok;
}
static int ec_asn1_group2curve(const EC_GROUP *group, X9_62_CURVE *curve)
{
int ok = 0, nid;
BIGNUM *tmp_1 = NULL, *tmp_2 = NULL;
- unsigned char *buffer_1 = NULL, *buffer_2 = NULL,
- *a_buf = NULL, *b_buf = NULL;
- size_t len_1, len_2;
- unsigned char char_zero = 0;
+ unsigned char *a_buf = NULL, *b_buf = NULL;
+ size_t len;
if (!group || !curve || !curve->a || !curve->b)
return 0;
}
}
#endif
- len_1 = (size_t)BN_num_bytes(tmp_1);
- len_2 = (size_t)BN_num_bytes(tmp_2);
-
- if (len_1 == 0) {
- /* len_1 == 0 => a == 0 */
- a_buf = &char_zero;
- len_1 = 1;
- } else {
- if ((buffer_1 = OPENSSL_malloc(len_1)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((len_1 = BN_bn2bin(tmp_1, buffer_1)) == 0) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
- goto err;
- }
- a_buf = buffer_1;
+ /*
+ * Per SEC 1, the curve coefficients must be padded up to size. See C.2's
+ * definition of Curve, C.1's definition of FieldElement, and 2.3.5's
+ * definition of how to encode the field elements.
+ */
+ len = ((size_t)EC_GROUP_get_degree(group) + 7) / 8;
+ if ((a_buf = OPENSSL_malloc(len)) == NULL
+ || (b_buf = OPENSSL_malloc(len)) == NULL) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
+ goto err;
}
-
- if (len_2 == 0) {
- /* len_2 == 0 => b == 0 */
- b_buf = &char_zero;
- len_2 = 1;
- } else {
- if ((buffer_2 = OPENSSL_malloc(len_2)) == NULL) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_MALLOC_FAILURE);
- goto err;
- }
- if ((len_2 = BN_bn2bin(tmp_2, buffer_2)) == 0) {
- ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
- goto err;
- }
- b_buf = buffer_2;
+ if (BN_bn2binpad(tmp_1, a_buf, len) < 0
+ || BN_bn2binpad(tmp_2, b_buf, len) < 0) {
+ ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_BN_LIB);
+ goto err;
}
/* set a and b */
- if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len_1) ||
- !ASN1_OCTET_STRING_set(curve->b, b_buf, len_2)) {
+ if (!ASN1_OCTET_STRING_set(curve->a, a_buf, len)
+ || !ASN1_OCTET_STRING_set(curve->b, b_buf, len)) {
ECerr(EC_F_EC_ASN1_GROUP2CURVE, ERR_R_ASN1_LIB);
goto err;
}
ok = 1;
err:
- OPENSSL_free(buffer_1);
- OPENSSL_free(buffer_2);
+ OPENSSL_free(a_buf);
+ OPENSSL_free(b_buf);
BN_free(tmp_1);
BN_free(tmp_2);
- return (ok);
+ return ok;
}
ECPARAMETERS *EC_GROUP_get_ecparameters(const EC_GROUP *group,
goto err;
}
if (ret->base == NULL && (ret->base = ASN1_OCTET_STRING_new()) == NULL) {
+ OPENSSL_free(buffer);
ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_MALLOC_FAILURE);
goto err;
}
- if (!ASN1_OCTET_STRING_set(ret->base, buffer, len)) {
- ECerr(EC_F_EC_GROUP_GET_ECPARAMETERS, ERR_R_ASN1_LIB);
- goto err;
- }
+ ASN1_STRING_set0(ret->base, buffer, len);
/* set the order */
tmp = EC_GROUP_get0_order(group);
err:
if (params == NULL)
ECPARAMETERS_free(ret);
- OPENSSL_free(buffer);
return NULL;
}
if (EC_GROUP_get_asn1_flag(group)) {
/*
- * use the asn1 OID to describe the the elliptic curve parameters
+ * use the asn1 OID to describe the elliptic curve parameters
*/
tmp = EC_GROUP_get_curve_name(group);
if (tmp) {
goto err;
}
- /* now extract the curve parameters a and b */
+ /*
+ * Now extract the curve parameters a and b. Note that, although SEC 1
+ * specifies the length of their encodings, historical versions of OpenSSL
+ * encoded them incorrectly, so we must accept any length for backwards
+ * compatibility.
+ */
if (!params->curve || !params->curve->a ||
!params->curve->a->data || !params->curve->b ||
!params->curve->b->data) {
BN_free(a);
BN_free(b);
EC_POINT_free(point);
- return (ret);
+ return ret;
}
EC_GROUP *EC_GROUP_new_from_ecpkparameters(const ECPKPARAMETERS *params)
ECPKPARAMETERS_free(params);
*in = p;
- return (group);
+ return group;
}
int i2d_ECPKParameters(const EC_GROUP *a, unsigned char **out)
return 0;
}
ECPKPARAMETERS_free(tmp);
- return (ret);
+ return ret;
}
/* some EC_KEY functions */
if (priv_key->privateKey) {
ASN1_OCTET_STRING *pkey = priv_key->privateKey;
- if (EC_KEY_oct2priv(ret, ASN1_STRING_data(pkey),
+ if (EC_KEY_oct2priv(ret, ASN1_STRING_get0_data(pkey),
ASN1_STRING_length(pkey)) == 0)
goto err;
} else {
const unsigned char *pub_oct;
int pub_oct_len;
- pub_oct = ASN1_STRING_data(priv_key->publicKey);
+ pub_oct = ASN1_STRING_get0_data(priv_key->publicKey);
pub_oct_len = ASN1_STRING_length(priv_key->publicKey);
if (!EC_KEY_oct2key(ret, pub_oct, pub_oct_len, NULL)) {
ECerr(EC_F_D2I_ECPRIVATEKEY, ERR_R_EC_LIB);
*a = ret;
EC_PRIVATEKEY_free(priv_key);
*in = p;
- return (ret);
+ return ret;
err:
if (a == NULL || *a != ret)
return ret;
}
-int i2o_ECPublicKey(EC_KEY *a, unsigned char **out)
+int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
{
size_t buf_len = 0;
int new_buffer = 0;
DECLARE_ASN1_FUNCTIONS_const(ECDSA_SIG)
DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECDSA_SIG, ECDSA_SIG)
-IMPLEMENT_ASN1_FUNCTIONS_const(ECDSA_SIG)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG)
+
+ECDSA_SIG *ECDSA_SIG_new(void)
+{
+ ECDSA_SIG *sig = OPENSSL_zalloc(sizeof(*sig));
+ if (sig == NULL)
+ ECerr(EC_F_ECDSA_SIG_NEW, ERR_R_MALLOC_FAILURE);
+ return sig;
+}
-void ECDSA_SIG_get0(BIGNUM **pr, BIGNUM **ps, const ECDSA_SIG *sig)
+void ECDSA_SIG_free(ECDSA_SIG *sig)
+{
+ if (sig == NULL)
+ return;
+ BN_clear_free(sig->r);
+ BN_clear_free(sig->s);
+ OPENSSL_free(sig);
+}
+
+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
{
if (pr != NULL)
*pr = sig->r;
*ps = sig->s;
}
-int ECDSA_SIG_set0(BIGNUM *r, BIGNUM *s, ECDSA_SIG *sig)
+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
{
+ if (r == NULL || s == NULL)
+ return 0;
BN_clear_free(sig->r);
BN_clear_free(sig->s);
sig->r = r;
i = i2d_ASN1_INTEGER(&bs, NULL);
i += i; /* r and s */
ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
- return (ret);
+ return ret;
}