From 7aa3571aba92d82f8dd3caabe48fad636f05a0fd Mon Sep 17 00:00:00 2001 From: djm <> Date: Thu, 5 Jan 2012 22:59:08 +0000 Subject: OpenSSL 1.0.0f: import upstream source --- src/lib/libcrypto/ecdsa/ecdsatest.c | 85 +++++++++++++-- src/lib/libcrypto/x509v3/v3_addr.c | 125 +++++++++++++++------- src/lib/libssl/src/apps/cms.c | 2 +- src/lib/libssl/src/crypto/bn/asm/x86-mont.pl | 4 +- src/lib/libssl/src/crypto/ec/ec2_smpl.c | 2 +- src/lib/libssl/src/crypto/ecdsa/ecdsatest.c | 85 +++++++++++++-- src/lib/libssl/src/crypto/x509v3/v3_addr.c | 125 +++++++++++++++------- src/lib/libssl/src/engines/ccgost/gost2001_keyx.c | 4 + src/lib/libssl/src/engines/ccgost/gost94_keyx.c | 4 + src/lib/libssl/src/ssl/d1_both.c | 23 ++-- src/lib/libssl/src/ssl/d1_lib.c | 9 +- src/lib/libssl/src/ssl/d1_pkt.c | 26 +++-- src/lib/libssl/src/ssl/d1_srvr.c | 2 +- 13 files changed, 380 insertions(+), 116 deletions(-) (limited to 'src') diff --git a/src/lib/libcrypto/ecdsa/ecdsatest.c b/src/lib/libcrypto/ecdsa/ecdsatest.c index 26a4a9ee7c..54cfb8c753 100644 --- a/src/lib/libcrypto/ecdsa/ecdsatest.c +++ b/src/lib/libcrypto/ecdsa/ecdsatest.c @@ -286,9 +286,12 @@ int test_builtin(BIO *out) size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; + ECDSA_SIG *ecdsa_sig = NULL; unsigned char digest[20], wrong_digest[20]; - unsigned char *signature = NULL; - unsigned int sig_len; + unsigned char *signature = NULL; + unsigned char *sig_ptr; + unsigned char *raw_buf = NULL; + unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ @@ -338,7 +341,8 @@ int test_builtin(BIO *out) if (EC_KEY_set_group(eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); - if (EC_GROUP_get_degree(EC_KEY_get0_group(eckey)) < 160) + degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); + if (degree < 160) /* drop the curve */ { EC_KEY_free(eckey); @@ -414,26 +418,89 @@ int test_builtin(BIO *out) } BIO_printf(out, "."); (void)BIO_flush(out); - /* modify a single byte of the signature */ - offset = signature[10] % sig_len; - dirt = signature[11]; - signature[offset] ^= dirt ? dirt : 1; + /* wrong length */ + if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, + eckey) == 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + BIO_printf(out, "."); + (void)BIO_flush(out); + + /* Modify a single byte of the signature: to ensure we don't + * garble the ASN1 structure, we read the raw signature and + * modify a byte in one of the bignums directly. */ + sig_ptr = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + + /* Store the two BIGNUMs in raw_buf. */ + r_len = BN_num_bytes(ecdsa_sig->r); + s_len = BN_num_bytes(ecdsa_sig->s); + bn_len = (degree + 7) / 8; + if ((r_len > bn_len) || (s_len > bn_len)) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + buf_len = 2 * bn_len; + if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL) + goto builtin_err; + /* Pad the bignums with leading zeroes. */ + memset(raw_buf, 0, buf_len); + BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len); + BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len); + + /* Modify a single byte in the buffer. */ + offset = raw_buf[10] % buf_len; + dirt = raw_buf[11] ? raw_buf[11] : 1; + raw_buf[offset] ^= dirt; + /* Now read the BIGNUMs back in from raw_buf. */ + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } + /* Sanity check: undo the modification and verify signature. */ + raw_buf[offset] ^= dirt; + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); + if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); /* cleanup */ + /* clean bogus errors */ + ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; + ECDSA_SIG_free(ecdsa_sig); + ecdsa_sig = NULL; + OPENSSL_free(raw_buf); + raw_buf = NULL; } ret = 1; @@ -442,8 +509,12 @@ builtin_err: EC_KEY_free(eckey); if (wrong_eckey) EC_KEY_free(wrong_eckey); + if (ecdsa_sig) + ECDSA_SIG_free(ecdsa_sig); if (signature) OPENSSL_free(signature); + if (raw_buf) + OPENSSL_free(raw_buf); if (curves) OPENSSL_free(curves); diff --git a/src/lib/libcrypto/x509v3/v3_addr.c b/src/lib/libcrypto/x509v3/v3_addr.c index 0d70e8696d..df46a4983b 100644 --- a/src/lib/libcrypto/x509v3/v3_addr.c +++ b/src/lib/libcrypto/x509v3/v3_addr.c @@ -142,12 +142,13 @@ unsigned int v3_addr_get_afi(const IPAddressFamily *f) * Expand the bitstring form of an address into a raw byte array. * At the moment this is coded for simplicity, not speed. */ -static void addr_expand(unsigned char *addr, +static int addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, const unsigned char fill) { - OPENSSL_assert(bs->length >= 0 && bs->length <= length); + if (bs->length < 0 || bs->length > length) + return 0; if (bs->length > 0) { memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { @@ -159,6 +160,7 @@ static void addr_expand(unsigned char *addr, } } memset(addr + bs->length, fill, length - bs->length); + return 1; } /* @@ -181,15 +183,13 @@ static int i2r_address(BIO *out, return 0; switch (afi) { case IANA_AFI_IPV4: - if (bs->length > 4) + if (!addr_expand(addr, bs, 4, fill)) return 0; - addr_expand(addr, bs, 4, fill); BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); break; case IANA_AFI_IPV6: - if (bs->length > 16) + if (!addr_expand(addr, bs, 16, fill)) return 0; - addr_expand(addr, bs, 16, fill); for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) ; for (i = 0; i < n; i += 2) @@ -315,6 +315,12 @@ static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, /* * Sort comparison function for a sequence of IPAddressOrRange * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. */ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, @@ -326,22 +332,26 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, switch (a->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_a, a->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; prefixlen_a = addr_prefixlen(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_a, a->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; prefixlen_a = length * 8; break; } switch (b->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_b, b->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; prefixlen_b = addr_prefixlen(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_b, b->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; prefixlen_b = length * 8; break; } @@ -383,6 +393,7 @@ static int range_should_be_prefix(const unsigned char *min, unsigned char mask; int i, j; + OPENSSL_assert(memcmp(min, max, length) <= 0); for (i = 0; i < length && min[i] == max[i]; i++) ; for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) @@ -601,10 +612,10 @@ static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, return NULL; switch (afi) { case IANA_AFI_IPV4: - sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); + (void) sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); break; case IANA_AFI_IPV6: - sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); + (void) sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); break; } f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; @@ -656,22 +667,22 @@ int v3_addr_add_range(IPAddrBlocks *addr, /* * Extract min and max values from an IPAddressOrRange. */ -static void extract_min_max(IPAddressOrRange *aor, +static int extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length) { - OPENSSL_assert(aor != NULL && min != NULL && max != NULL); + if (aor == NULL || min == NULL || max == NULL) + return 0; switch (aor->type) { case IPAddressOrRange_addressPrefix: - addr_expand(min, aor->u.addressPrefix, length, 0x00); - addr_expand(max, aor->u.addressPrefix, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && + addr_expand(max, aor->u.addressPrefix, length, 0xFF)); case IPAddressOrRange_addressRange: - addr_expand(min, aor->u.addressRange->min, length, 0x00); - addr_expand(max, aor->u.addressRange->max, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && + addr_expand(max, aor->u.addressRange->max, length, 0xFF)); } + return 0; } /* @@ -687,9 +698,10 @@ int v3_addr_get_range(IPAddressOrRange *aor, if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && - aor->type != IPAddressOrRange_addressRange)) + aor->type != IPAddressOrRange_addressRange) || + !extract_min_max(aor, min, max, afi_length)) return 0; - extract_min_max(aor, min, max, afi_length); + return afi_length; } @@ -771,8 +783,9 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; /* * Punt misordered list, overlapping start, or inverted range. @@ -800,14 +813,17 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) } /* - * Check final range to see if it should be a prefix. + * Check range to see if it's inverted or should be a + * prefix. */ j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a->type == IPAddressOrRange_addressRange) { - extract_min_max(a, a_min, a_max, length); - if (range_should_be_prefix(a_min, a_max, length) >= 0) + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0 || + range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } } @@ -841,8 +857,16 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; /* * Punt overlaps. @@ -860,8 +884,8 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, IPAddressOrRange *merged; if (!make_addressRange(&merged, a_min, b_max, length)) return 0; - sk_IPAddressOrRange_set(aors, i, merged); - sk_IPAddressOrRange_delete(aors, i + 1); + (void) sk_IPAddressOrRange_set(aors, i, merged); + (void) sk_IPAddressOrRange_delete(aors, i + 1); IPAddressOrRange_free(a); IPAddressOrRange_free(b); --i; @@ -869,6 +893,20 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, } } + /* + * Check for inverted final range. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + extract_min_max(a, a_min, a_max, length); + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + return 1; } @@ -885,7 +923,7 @@ int v3_addr_canonize(IPAddrBlocks *addr) v3_addr_get_afi(f))) return 0; } - sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); sk_IPAddressFamily_sort(addr); OPENSSL_assert(v3_addr_is_canonical(addr)); return 1; @@ -1017,6 +1055,11 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, X509V3_conf_err(val); goto err; } + if (memcmp(min, max, length_from_afi(afi)) > 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } if (!v3_addr_add_range(addr, afi, safi, min, max)) { X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); goto err; @@ -1102,13 +1145,15 @@ static int addr_contains(IPAddressOrRanges *parent, p = 0; for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { - extract_min_max(sk_IPAddressOrRange_value(child, c), - c_min, c_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(child, c), + c_min, c_max, length)) + return -1; for (;; p++) { if (p >= sk_IPAddressOrRange_num(parent)) return 0; - extract_min_max(sk_IPAddressOrRange_value(parent, p), - p_min, p_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), + p_min, p_max, length)) + return 0; if (memcmp(p_max, c_max, length) < 0) continue; if (memcmp(p_min, c_min, length) > 0) @@ -1130,7 +1175,7 @@ int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) return 1; if (b == NULL || v3_addr_inherits(a) || v3_addr_inherits(b)) return 0; - sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); for (i = 0; i < sk_IPAddressFamily_num(a); i++) { IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); int j = sk_IPAddressFamily_find(b, fa); @@ -1195,7 +1240,7 @@ static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx, } if (!v3_addr_is_canonical(ext)) validation_err(X509_V_ERR_INVALID_EXTENSION); - sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL, ERR_R_MALLOC_FAILURE); ret = 0; @@ -1221,7 +1266,7 @@ static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx, } continue; } - sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); for (j = 0; j < sk_IPAddressFamily_num(child); j++) { IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); diff --git a/src/lib/libssl/src/apps/cms.c b/src/lib/libssl/src/apps/cms.c index d29a884902..3f5ee1b577 100644 --- a/src/lib/libssl/src/apps/cms.c +++ b/src/lib/libssl/src/apps/cms.c @@ -618,7 +618,7 @@ int MAIN(int argc, char **argv) BIO_printf (bio_err, "-certsout file certificate output file\n"); BIO_printf (bio_err, "-signer file signer certificate file\n"); BIO_printf (bio_err, "-recip file recipient certificate file for decryption\n"); - BIO_printf (bio_err, "-skeyid use subject key identifier\n"); + BIO_printf (bio_err, "-keyid use subject key identifier\n"); BIO_printf (bio_err, "-in file input file\n"); BIO_printf (bio_err, "-inform arg input format SMIME (default), PEM or DER\n"); BIO_printf (bio_err, "-inkey file input private key (if not signer or recipient)\n"); diff --git a/src/lib/libssl/src/crypto/bn/asm/x86-mont.pl b/src/lib/libssl/src/crypto/bn/asm/x86-mont.pl index 5cd3cd2ed5..e8f6b05084 100755 --- a/src/lib/libssl/src/crypto/bn/asm/x86-mont.pl +++ b/src/lib/libssl/src/crypto/bn/asm/x86-mont.pl @@ -527,8 +527,10 @@ $sbit=$num; &jle (&label("sqradd")); &mov ($carry,"edx"); - &lea ("edx",&DWP(0,$sbit,"edx",2)); + &add ("edx","edx"); &shr ($carry,31); + &add ("edx",$sbit); + &adc ($carry,0); &set_label("sqrlast"); &mov ($word,$_n0); &mov ($inp,$_np); diff --git a/src/lib/libssl/src/crypto/ec/ec2_smpl.c b/src/lib/libssl/src/crypto/ec/ec2_smpl.c index af94458ca7..03deae6674 100644 --- a/src/lib/libssl/src/crypto/ec/ec2_smpl.c +++ b/src/lib/libssl/src/crypto/ec/ec2_smpl.c @@ -887,7 +887,7 @@ int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_ field_sqr = group->meth->field_sqr; /* only support affine coordinates */ - if (!point->Z_is_one) goto err; + if (!point->Z_is_one) return -1; if (ctx == NULL) { diff --git a/src/lib/libssl/src/crypto/ecdsa/ecdsatest.c b/src/lib/libssl/src/crypto/ecdsa/ecdsatest.c index 26a4a9ee7c..54cfb8c753 100644 --- a/src/lib/libssl/src/crypto/ecdsa/ecdsatest.c +++ b/src/lib/libssl/src/crypto/ecdsa/ecdsatest.c @@ -286,9 +286,12 @@ int test_builtin(BIO *out) size_t crv_len = 0, n = 0; EC_KEY *eckey = NULL, *wrong_eckey = NULL; EC_GROUP *group; + ECDSA_SIG *ecdsa_sig = NULL; unsigned char digest[20], wrong_digest[20]; - unsigned char *signature = NULL; - unsigned int sig_len; + unsigned char *signature = NULL; + unsigned char *sig_ptr; + unsigned char *raw_buf = NULL; + unsigned int sig_len, degree, r_len, s_len, bn_len, buf_len; int nid, ret = 0; /* fill digest values with some random data */ @@ -338,7 +341,8 @@ int test_builtin(BIO *out) if (EC_KEY_set_group(eckey, group) == 0) goto builtin_err; EC_GROUP_free(group); - if (EC_GROUP_get_degree(EC_KEY_get0_group(eckey)) < 160) + degree = EC_GROUP_get_degree(EC_KEY_get0_group(eckey)); + if (degree < 160) /* drop the curve */ { EC_KEY_free(eckey); @@ -414,26 +418,89 @@ int test_builtin(BIO *out) } BIO_printf(out, "."); (void)BIO_flush(out); - /* modify a single byte of the signature */ - offset = signature[10] % sig_len; - dirt = signature[11]; - signature[offset] ^= dirt ? dirt : 1; + /* wrong length */ + if (ECDSA_verify(0, digest, 20, signature, sig_len - 1, + eckey) == 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + BIO_printf(out, "."); + (void)BIO_flush(out); + + /* Modify a single byte of the signature: to ensure we don't + * garble the ASN1 structure, we read the raw signature and + * modify a byte in one of the bignums directly. */ + sig_ptr = signature; + if ((ecdsa_sig = d2i_ECDSA_SIG(NULL, &sig_ptr, sig_len)) == NULL) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + + /* Store the two BIGNUMs in raw_buf. */ + r_len = BN_num_bytes(ecdsa_sig->r); + s_len = BN_num_bytes(ecdsa_sig->s); + bn_len = (degree + 7) / 8; + if ((r_len > bn_len) || (s_len > bn_len)) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } + buf_len = 2 * bn_len; + if ((raw_buf = OPENSSL_malloc(buf_len)) == NULL) + goto builtin_err; + /* Pad the bignums with leading zeroes. */ + memset(raw_buf, 0, buf_len); + BN_bn2bin(ecdsa_sig->r, raw_buf + bn_len - r_len); + BN_bn2bin(ecdsa_sig->s, raw_buf + buf_len - s_len); + + /* Modify a single byte in the buffer. */ + offset = raw_buf[10] % buf_len; + dirt = raw_buf[11] ? raw_buf[11] : 1; + raw_buf[offset] ^= dirt; + /* Now read the BIGNUMs back in from raw_buf. */ + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) == 1) { BIO_printf(out, " failed\n"); goto builtin_err; } + /* Sanity check: undo the modification and verify signature. */ + raw_buf[offset] ^= dirt; + if ((BN_bin2bn(raw_buf, bn_len, ecdsa_sig->r) == NULL) || + (BN_bin2bn(raw_buf + bn_len, bn_len, ecdsa_sig->s) == NULL)) + goto builtin_err; + + sig_ptr = signature; + sig_len = i2d_ECDSA_SIG(ecdsa_sig, &sig_ptr); + if (ECDSA_verify(0, digest, 20, signature, sig_len, eckey) != 1) + { + BIO_printf(out, " failed\n"); + goto builtin_err; + } BIO_printf(out, "."); (void)BIO_flush(out); BIO_printf(out, " ok\n"); /* cleanup */ + /* clean bogus errors */ + ERR_clear_error(); OPENSSL_free(signature); signature = NULL; EC_KEY_free(eckey); eckey = NULL; EC_KEY_free(wrong_eckey); wrong_eckey = NULL; + ECDSA_SIG_free(ecdsa_sig); + ecdsa_sig = NULL; + OPENSSL_free(raw_buf); + raw_buf = NULL; } ret = 1; @@ -442,8 +509,12 @@ builtin_err: EC_KEY_free(eckey); if (wrong_eckey) EC_KEY_free(wrong_eckey); + if (ecdsa_sig) + ECDSA_SIG_free(ecdsa_sig); if (signature) OPENSSL_free(signature); + if (raw_buf) + OPENSSL_free(raw_buf); if (curves) OPENSSL_free(curves); diff --git a/src/lib/libssl/src/crypto/x509v3/v3_addr.c b/src/lib/libssl/src/crypto/x509v3/v3_addr.c index 0d70e8696d..df46a4983b 100644 --- a/src/lib/libssl/src/crypto/x509v3/v3_addr.c +++ b/src/lib/libssl/src/crypto/x509v3/v3_addr.c @@ -142,12 +142,13 @@ unsigned int v3_addr_get_afi(const IPAddressFamily *f) * Expand the bitstring form of an address into a raw byte array. * At the moment this is coded for simplicity, not speed. */ -static void addr_expand(unsigned char *addr, +static int addr_expand(unsigned char *addr, const ASN1_BIT_STRING *bs, const int length, const unsigned char fill) { - OPENSSL_assert(bs->length >= 0 && bs->length <= length); + if (bs->length < 0 || bs->length > length) + return 0; if (bs->length > 0) { memcpy(addr, bs->data, bs->length); if ((bs->flags & 7) != 0) { @@ -159,6 +160,7 @@ static void addr_expand(unsigned char *addr, } } memset(addr + bs->length, fill, length - bs->length); + return 1; } /* @@ -181,15 +183,13 @@ static int i2r_address(BIO *out, return 0; switch (afi) { case IANA_AFI_IPV4: - if (bs->length > 4) + if (!addr_expand(addr, bs, 4, fill)) return 0; - addr_expand(addr, bs, 4, fill); BIO_printf(out, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); break; case IANA_AFI_IPV6: - if (bs->length > 16) + if (!addr_expand(addr, bs, 16, fill)) return 0; - addr_expand(addr, bs, 16, fill); for (n = 16; n > 1 && addr[n-1] == 0x00 && addr[n-2] == 0x00; n -= 2) ; for (i = 0; i < n; i += 2) @@ -315,6 +315,12 @@ static int i2r_IPAddrBlocks(const X509V3_EXT_METHOD *method, /* * Sort comparison function for a sequence of IPAddressOrRange * elements. + * + * There's no sane answer we can give if addr_expand() fails, and an + * assertion failure on externally supplied data is seriously uncool, + * so we just arbitrarily declare that if given invalid inputs this + * function returns -1. If this messes up your preferred sort order + * for garbage input, tough noogies. */ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, const IPAddressOrRange *b, @@ -326,22 +332,26 @@ static int IPAddressOrRange_cmp(const IPAddressOrRange *a, switch (a->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_a, a->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_a, a->u.addressPrefix, length, 0x00)) + return -1; prefixlen_a = addr_prefixlen(a->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_a, a->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_a, a->u.addressRange->min, length, 0x00)) + return -1; prefixlen_a = length * 8; break; } switch (b->type) { case IPAddressOrRange_addressPrefix: - addr_expand(addr_b, b->u.addressPrefix, length, 0x00); + if (!addr_expand(addr_b, b->u.addressPrefix, length, 0x00)) + return -1; prefixlen_b = addr_prefixlen(b->u.addressPrefix); break; case IPAddressOrRange_addressRange: - addr_expand(addr_b, b->u.addressRange->min, length, 0x00); + if (!addr_expand(addr_b, b->u.addressRange->min, length, 0x00)) + return -1; prefixlen_b = length * 8; break; } @@ -383,6 +393,7 @@ static int range_should_be_prefix(const unsigned char *min, unsigned char mask; int i, j; + OPENSSL_assert(memcmp(min, max, length) <= 0); for (i = 0; i < length && min[i] == max[i]; i++) ; for (j = length - 1; j >= 0 && min[j] == 0x00 && max[j] == 0xFF; j--) @@ -601,10 +612,10 @@ static IPAddressOrRanges *make_prefix_or_range(IPAddrBlocks *addr, return NULL; switch (afi) { case IANA_AFI_IPV4: - sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); + (void) sk_IPAddressOrRange_set_cmp_func(aors, v4IPAddressOrRange_cmp); break; case IANA_AFI_IPV6: - sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); + (void) sk_IPAddressOrRange_set_cmp_func(aors, v6IPAddressOrRange_cmp); break; } f->ipAddressChoice->type = IPAddressChoice_addressesOrRanges; @@ -656,22 +667,22 @@ int v3_addr_add_range(IPAddrBlocks *addr, /* * Extract min and max values from an IPAddressOrRange. */ -static void extract_min_max(IPAddressOrRange *aor, +static int extract_min_max(IPAddressOrRange *aor, unsigned char *min, unsigned char *max, int length) { - OPENSSL_assert(aor != NULL && min != NULL && max != NULL); + if (aor == NULL || min == NULL || max == NULL) + return 0; switch (aor->type) { case IPAddressOrRange_addressPrefix: - addr_expand(min, aor->u.addressPrefix, length, 0x00); - addr_expand(max, aor->u.addressPrefix, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressPrefix, length, 0x00) && + addr_expand(max, aor->u.addressPrefix, length, 0xFF)); case IPAddressOrRange_addressRange: - addr_expand(min, aor->u.addressRange->min, length, 0x00); - addr_expand(max, aor->u.addressRange->max, length, 0xFF); - return; + return (addr_expand(min, aor->u.addressRange->min, length, 0x00) && + addr_expand(max, aor->u.addressRange->max, length, 0xFF)); } + return 0; } /* @@ -687,9 +698,10 @@ int v3_addr_get_range(IPAddressOrRange *aor, if (aor == NULL || min == NULL || max == NULL || afi_length == 0 || length < afi_length || (aor->type != IPAddressOrRange_addressPrefix && - aor->type != IPAddressOrRange_addressRange)) + aor->type != IPAddressOrRange_addressRange) || + !extract_min_max(aor, min, max, afi_length)) return 0; - extract_min_max(aor, min, max, afi_length); + return afi_length; } @@ -771,8 +783,9 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); IPAddressOrRange *b = sk_IPAddressOrRange_value(aors, j + 1); - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; /* * Punt misordered list, overlapping start, or inverted range. @@ -800,14 +813,17 @@ int v3_addr_is_canonical(IPAddrBlocks *addr) } /* - * Check final range to see if it should be a prefix. + * Check range to see if it's inverted or should be a + * prefix. */ j = sk_IPAddressOrRange_num(aors) - 1; { IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); - if (a->type == IPAddressOrRange_addressRange) { - extract_min_max(a, a_min, a_max, length); - if (range_should_be_prefix(a_min, a_max, length) >= 0) + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + if (!extract_min_max(a, a_min, a_max, length)) + return 0; + if (memcmp(a_min, a_max, length) > 0 || + range_should_be_prefix(a_min, a_max, length) >= 0) return 0; } } @@ -841,8 +857,16 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; unsigned char b_min[ADDR_RAW_BUF_LEN], b_max[ADDR_RAW_BUF_LEN]; - extract_min_max(a, a_min, a_max, length); - extract_min_max(b, b_min, b_max, length); + if (!extract_min_max(a, a_min, a_max, length) || + !extract_min_max(b, b_min, b_max, length)) + return 0; + + /* + * Punt inverted ranges. + */ + if (memcmp(a_min, a_max, length) > 0 || + memcmp(b_min, b_max, length) > 0) + return 0; /* * Punt overlaps. @@ -860,8 +884,8 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, IPAddressOrRange *merged; if (!make_addressRange(&merged, a_min, b_max, length)) return 0; - sk_IPAddressOrRange_set(aors, i, merged); - sk_IPAddressOrRange_delete(aors, i + 1); + (void) sk_IPAddressOrRange_set(aors, i, merged); + (void) sk_IPAddressOrRange_delete(aors, i + 1); IPAddressOrRange_free(a); IPAddressOrRange_free(b); --i; @@ -869,6 +893,20 @@ static int IPAddressOrRanges_canonize(IPAddressOrRanges *aors, } } + /* + * Check for inverted final range. + */ + j = sk_IPAddressOrRange_num(aors) - 1; + { + IPAddressOrRange *a = sk_IPAddressOrRange_value(aors, j); + if (a != NULL && a->type == IPAddressOrRange_addressRange) { + unsigned char a_min[ADDR_RAW_BUF_LEN], a_max[ADDR_RAW_BUF_LEN]; + extract_min_max(a, a_min, a_max, length); + if (memcmp(a_min, a_max, length) > 0) + return 0; + } + } + return 1; } @@ -885,7 +923,7 @@ int v3_addr_canonize(IPAddrBlocks *addr) v3_addr_get_afi(f))) return 0; } - sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(addr, IPAddressFamily_cmp); sk_IPAddressFamily_sort(addr); OPENSSL_assert(v3_addr_is_canonical(addr)); return 1; @@ -1017,6 +1055,11 @@ static void *v2i_IPAddrBlocks(const struct v3_ext_method *method, X509V3_conf_err(val); goto err; } + if (memcmp(min, max, length_from_afi(afi)) > 0) { + X509V3err(X509V3_F_V2I_IPADDRBLOCKS, X509V3_R_EXTENSION_VALUE_ERROR); + X509V3_conf_err(val); + goto err; + } if (!v3_addr_add_range(addr, afi, safi, min, max)) { X509V3err(X509V3_F_V2I_IPADDRBLOCKS, ERR_R_MALLOC_FAILURE); goto err; @@ -1102,13 +1145,15 @@ static int addr_contains(IPAddressOrRanges *parent, p = 0; for (c = 0; c < sk_IPAddressOrRange_num(child); c++) { - extract_min_max(sk_IPAddressOrRange_value(child, c), - c_min, c_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(child, c), + c_min, c_max, length)) + return -1; for (;; p++) { if (p >= sk_IPAddressOrRange_num(parent)) return 0; - extract_min_max(sk_IPAddressOrRange_value(parent, p), - p_min, p_max, length); + if (!extract_min_max(sk_IPAddressOrRange_value(parent, p), + p_min, p_max, length)) + return 0; if (memcmp(p_max, c_max, length) < 0) continue; if (memcmp(p_min, c_min, length) > 0) @@ -1130,7 +1175,7 @@ int v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b) return 1; if (b == NULL || v3_addr_inherits(a) || v3_addr_inherits(b)) return 0; - sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(b, IPAddressFamily_cmp); for (i = 0; i < sk_IPAddressFamily_num(a); i++) { IPAddressFamily *fa = sk_IPAddressFamily_value(a, i); int j = sk_IPAddressFamily_find(b, fa); @@ -1195,7 +1240,7 @@ static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx, } if (!v3_addr_is_canonical(ext)) validation_err(X509_V_ERR_INVALID_EXTENSION); - sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(ext, IPAddressFamily_cmp); if ((child = sk_IPAddressFamily_dup(ext)) == NULL) { X509V3err(X509V3_F_V3_ADDR_VALIDATE_PATH_INTERNAL, ERR_R_MALLOC_FAILURE); ret = 0; @@ -1221,7 +1266,7 @@ static int v3_addr_validate_path_internal(X509_STORE_CTX *ctx, } continue; } - sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); + (void) sk_IPAddressFamily_set_cmp_func(x->rfc3779_addr, IPAddressFamily_cmp); for (j = 0; j < sk_IPAddressFamily_num(child); j++) { IPAddressFamily *fc = sk_IPAddressFamily_value(child, j); int k = sk_IPAddressFamily_find(x->rfc3779_addr, fc); diff --git a/src/lib/libssl/src/engines/ccgost/gost2001_keyx.c b/src/lib/libssl/src/engines/ccgost/gost2001_keyx.c index 00759bcab0..c748102857 100644 --- a/src/lib/libssl/src/engines/ccgost/gost2001_keyx.c +++ b/src/lib/libssl/src/engines/ccgost/gost2001_keyx.c @@ -280,6 +280,10 @@ int pkey_GOST01cp_decrypt(EVP_PKEY_CTX *pctx, unsigned char *key, size_t * key_l } param = get_encryption_params(gkt->key_agreement_info->cipher); + if(!param){ + goto err; + } + gost_init(&ctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); memcpy(wrappedKey,gkt->key_agreement_info->eph_iv->data,8); diff --git a/src/lib/libssl/src/engines/ccgost/gost94_keyx.c b/src/lib/libssl/src/engines/ccgost/gost94_keyx.c index 624be586a5..0d7d3ffe6a 100644 --- a/src/lib/libssl/src/engines/ccgost/gost94_keyx.c +++ b/src/lib/libssl/src/engines/ccgost/gost94_keyx.c @@ -261,6 +261,10 @@ int pkey_GOST94cp_decrypt(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *key_len } param = get_encryption_params(gkt->key_agreement_info->cipher); + if(!param){ + goto err; + } + gost_init(&cctx,param->sblock); OPENSSL_assert(gkt->key_agreement_info->eph_iv->length==8); memcpy(wrappedKey,gkt->key_agreement_info->eph_iv->data,8); diff --git a/src/lib/libssl/src/ssl/d1_both.c b/src/lib/libssl/src/ssl/d1_both.c index 2180c6d4da..9f898d6997 100644 --- a/src/lib/libssl/src/ssl/d1_both.c +++ b/src/lib/libssl/src/ssl/d1_both.c @@ -158,7 +158,6 @@ static unsigned char bitmask_end_values[] = {0xff, 0x01, 0x03, 0x07, 0x0f, 0x1 /* XDTLS: figure out the right values */ static unsigned int g_probable_mtu[] = {1500 - 28, 512 - 28, 256 - 28}; -static unsigned int dtls1_min_mtu(void); static unsigned int dtls1_guess_mtu(unsigned int curr_mtu); static void dtls1_fix_message_header(SSL *s, unsigned long frag_off, unsigned long frag_len); @@ -264,11 +263,10 @@ int dtls1_do_write(SSL *s, int type) return ret; mtu = s->d1->mtu - (DTLS1_HM_HEADER_LENGTH + DTLS1_RT_HEADER_LENGTH); } - - OPENSSL_assert(mtu > 0); /* should have something reasonable now */ - #endif + OPENSSL_assert(s->d1->mtu >= dtls1_min_mtu()); /* should have something reasonable now */ + if ( s->init_off == 0 && type == SSL3_RT_HANDSHAKE) OPENSSL_assert(s->init_num == (int)s->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH); @@ -795,7 +793,13 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) *ok = 0; return i; } - OPENSSL_assert(i == DTLS1_HM_HEADER_LENGTH); + /* Handshake fails if message header is incomplete */ + if (i != DTLS1_HM_HEADER_LENGTH) + { + al=SSL_AD_UNEXPECTED_MESSAGE; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL_R_UNEXPECTED_MESSAGE); + goto f_err; + } /* parse the message fragment header */ dtls1_get_message_header(wire, &msg_hdr); @@ -867,7 +871,12 @@ dtls1_get_message_fragment(SSL *s, int st1, int stn, long max, int *ok) /* XDTLS: an incorrectly formatted fragment should cause the * handshake to fail */ - OPENSSL_assert(i == (int)frag_len); + if (i != (int)frag_len) + { + al=SSL3_AD_ILLEGAL_PARAMETER; + SSLerr(SSL_F_DTLS1_GET_MESSAGE_FRAGMENT,SSL3_AD_ILLEGAL_PARAMETER); + goto f_err; + } *ok = 1; @@ -1367,7 +1376,7 @@ dtls1_write_message_header(SSL *s, unsigned char *p) return p; } -static unsigned int +unsigned int dtls1_min_mtu(void) { return (g_probable_mtu[(sizeof(g_probable_mtu) / diff --git a/src/lib/libssl/src/ssl/d1_lib.c b/src/lib/libssl/src/ssl/d1_lib.c index 48e8b6ffbb..c3b77c889b 100644 --- a/src/lib/libssl/src/ssl/d1_lib.c +++ b/src/lib/libssl/src/ssl/d1_lib.c @@ -204,7 +204,8 @@ void dtls1_clear(SSL *s) pqueue buffered_messages; pqueue sent_messages; pqueue buffered_app_data; - + unsigned int mtu; + if (s->d1) { unprocessed_rcds = s->d1->unprocessed_rcds.q; @@ -212,6 +213,7 @@ void dtls1_clear(SSL *s) buffered_messages = s->d1->buffered_messages; sent_messages = s->d1->sent_messages; buffered_app_data = s->d1->buffered_app_data.q; + mtu = s->d1->mtu; dtls1_clear_queues(s); @@ -222,6 +224,11 @@ void dtls1_clear(SSL *s) s->d1->cookie_len = sizeof(s->d1->cookie); } + if (SSL_get_options(s) & SSL_OP_NO_QUERY_MTU) + { + s->d1->mtu = mtu; + } + s->d1->unprocessed_rcds.q = unprocessed_rcds; s->d1->processed_rcds.q = processed_rcds; s->d1->buffered_messages = buffered_messages; diff --git a/src/lib/libssl/src/ssl/d1_pkt.c b/src/lib/libssl/src/ssl/d1_pkt.c index 39aac73e10..e0c0f0cc9a 100644 --- a/src/lib/libssl/src/ssl/d1_pkt.c +++ b/src/lib/libssl/src/ssl/d1_pkt.c @@ -375,6 +375,7 @@ dtls1_process_record(SSL *s) SSL3_RECORD *rr; unsigned int mac_size; unsigned char md[EVP_MAX_MD_SIZE]; + int decryption_failed_or_bad_record_mac = 0; rr= &(s->s3->rrec); @@ -409,13 +410,10 @@ dtls1_process_record(SSL *s) enc_err = s->method->ssl3_enc->enc(s,0); if (enc_err <= 0) { - /* decryption failed, silently discard message */ - if (enc_err < 0) - { - rr->length = 0; - s->packet_length = 0; - } - goto err; + /* To minimize information leaked via timing, we will always + * perform all computations before discarding the message. + */ + decryption_failed_or_bad_record_mac = 1; } #ifdef TLS_DEBUG @@ -445,7 +443,7 @@ printf("\n"); SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_PRE_MAC_LENGTH_TOO_LONG); goto f_err; #else - goto err; + decryption_failed_or_bad_record_mac = 1; #endif } /* check the MAC for rr->input (it's in mac_size bytes at the tail) */ @@ -456,17 +454,25 @@ printf("\n"); SSLerr(SSL_F_DTLS1_PROCESS_RECORD,SSL_R_LENGTH_TOO_SHORT); goto f_err; #else - goto err; + decryption_failed_or_bad_record_mac = 1; #endif } rr->length-=mac_size; i=s->method->ssl3_enc->mac(s,md,0); if (i < 0 || memcmp(md,&(rr->data[rr->length]),mac_size) != 0) { - goto err; + decryption_failed_or_bad_record_mac = 1; } } + if (decryption_failed_or_bad_record_mac) + { + /* decryption failed, silently discard message */ + rr->length = 0; + s->packet_length = 0; + goto err; + } + /* r->length is now just compressed */ if (s->expand != NULL) { diff --git a/src/lib/libssl/src/ssl/d1_srvr.c b/src/lib/libssl/src/ssl/d1_srvr.c index a6a4c87ea6..149983be30 100644 --- a/src/lib/libssl/src/ssl/d1_srvr.c +++ b/src/lib/libssl/src/ssl/d1_srvr.c @@ -1271,7 +1271,7 @@ int dtls1_send_server_key_exchange(SSL *s) EVP_SignInit_ex(&md_ctx,EVP_ecdsa(), NULL); EVP_SignUpdate(&md_ctx,&(s->s3->client_random[0]),SSL3_RANDOM_SIZE); EVP_SignUpdate(&md_ctx,&(s->s3->server_random[0]),SSL3_RANDOM_SIZE); - EVP_SignUpdate(&md_ctx,&(d[4]),n); + EVP_SignUpdate(&md_ctx,&(d[DTLS1_HM_HEADER_LENGTH]),n); if (!EVP_SignFinal(&md_ctx,&(p[2]), (unsigned int *)&i,pkey)) { -- cgit v1.2.3-55-g6feb