/* * Compute shared secret (SEC1 3.3.1) */ int ecdh_compute_shared( ecp_group *grp, mpi *z, const ecp_point *Q, const mpi *d, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; ecp_point P; ecp_point_init( &P ); /* * Make sure Q is a valid pubkey before using it */ MPI_CHK( ecp_check_pubkey( grp, Q ) ); MPI_CHK( ecp_mul( grp, &P, d, Q, f_rng, p_rng ) ); if( ecp_is_zero( &P ) ) { ret = POLARSSL_ERR_ECP_BAD_INPUT_DATA; goto cleanup; } MPI_CHK( mpi_copy( z, &P.X ) ); cleanup: ecp_point_free( &P ); return( ret ); }
/* * Parse a SEC1 encoded private EC key */ static int pk_parse_key_sec1_der( ecp_keypair *eck, const unsigned char *key, size_t keylen ) { int ret; int version, pubkey_done; size_t len; asn1_buf params; unsigned char *p = (unsigned char *) key; unsigned char *end = p + keylen; unsigned char *end2; /* * RFC 5915, or SEC1 Appendix C.4 * * ECPrivateKey ::= SEQUENCE { * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), * privateKey OCTET STRING, * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, * publicKey [1] BIT STRING OPTIONAL * } */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ) != 0 ) { return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } end = p + len; if( ( ret = asn1_get_int( &p, end, &version ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( version != 1 ) return( POLARSSL_ERR_PK_KEY_INVALID_VERSION ); if( ( ret = asn1_get_tag( &p, end, &len, ASN1_OCTET_STRING ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( ( ret = shmpi_read_binary( &eck->d, p, len ) ) != 0 ) { ecp_keypair_free( eck ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } p += len; pubkey_done = 0; if( p != end ) { /* * Is 'parameters' present? */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ) == 0 ) { if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); } } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { ecp_keypair_free( eck ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } /* * Is 'publickey' present? If not, or if we can't read it (eg because it * is compressed), create it from the private key. */ if( ( ret = asn1_get_tag( &p, end, &len, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 1 ) ) == 0 ) { end2 = p + len; if( ( ret = asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); if( p + len != end2 ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + POLARSSL_ERR_ASN1_LENGTH_MISMATCH ); if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) pubkey_done = 1; else { /* * The only acceptable failure mode of pk_get_ecpubkey() above * is if the point format is not recognized. */ if( ret != POLARSSL_ERR_ECP_FEATURE_UNAVAILABLE ) return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT ); } } else if( ret != POLARSSL_ERR_ASN1_UNEXPECTED_TAG ) { ecp_keypair_free( eck ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } } if( ! pubkey_done && ( ret = ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, NULL, NULL ) ) != 0 ) { ecp_keypair_free( eck ); return( POLARSSL_ERR_PK_KEY_INVALID_FORMAT + ret ); } if( ( ret = ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) { ecp_keypair_free( eck ); return( ret ); } return( 0 ); }