Exemplo n.º 1
0
int dslink_handshake_read_key_pair(mbedtls_ecdh_context *ctx, char *buf) {
    mbedtls_ecdh_init(ctx);
    dslink_handshake_get_group(&ctx->grp);
    char *q = strchr(buf, ' ');
    if (!q || *(q + 1) == '\0') {
        errno = 0;
        return DSLINK_CRYPT_KEY_DECODE_ERR;
    }

    size_t len = (q - buf);
    unsigned char dec[90];
    size_t decLen = 0;
    if (dslink_base64_url_decode(dec, sizeof(dec), &decLen,
                                 (unsigned char *) buf, len) != 0) {
        return DSLINK_CRYPT_BASE64_URL_DECODE_ERR;
    }

    if ((errno = mbedtls_mpi_read_binary(&ctx->d, dec, decLen)) != 0) {
        return DSLINK_CRYPT_KEY_DECODE_ERR;
    }

    len = strlen(buf) - len - 1;
    if (dslink_base64_url_decode(dec, sizeof(dec), &decLen,
                                 (unsigned char *) (q + 1), len) != 0) {
        return DSLINK_CRYPT_BASE64_URL_DECODE_ERR;
    }

    if ((errno = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q,
                                               dec, decLen)) != 0) {
        return DSLINK_CRYPT_KEY_DECODE_ERR;
    }

    return 0;
}
Exemplo n.º 2
0
static
int gen_auth_key(mbedtls_ecdh_context *key, const char *tempKey,
                 const char *salt, unsigned char *buf, size_t bufLen) {
    int ret = 0;
    size_t olen = 0;
    if ((errno = dslink_base64_url_decode(buf, bufLen, &olen,
                                          (unsigned char *) tempKey,
                                          strlen(tempKey))) != 0) {
        ret = DSLINK_CRYPT_BASE64_URL_DECODE_ERR;
        goto exit;
    }

    if ((errno = mbedtls_ecp_point_read_binary(&key->grp, &key->Qp,
                                               buf, olen)) != 0) {
        ret = DSLINK_HANDSHAKE_INVALID_TMP_KEY;
        goto exit;
    }

    if ((errno = mbedtls_ecdh_calc_secret(key, &olen, buf,
                                          bufLen, NULL, NULL)) != 0) {
        ret = DSLINK_HANDSHAKE_INVALID_TMP_KEY;
        goto exit;
    }

    {
        size_t saltLen = strlen(salt);
        size_t len = saltLen + olen;
        char *in = malloc(len + 1);
        if (!in) {
            ret = DSLINK_ALLOC_ERR;
            goto exit;
        }
        memcpy(in, salt, saltLen);
        memcpy(in + saltLen, (char *) buf, olen);
        *(in + len) = '\0';

        unsigned char auth[32];
        mbedtls_sha256((unsigned char *) in, len, auth, 0);
        free(in);

        if ((errno = dslink_base64_url_encode(buf, bufLen, &olen, auth,
                                              sizeof(auth))) != 0) {
            ret = DSLINK_CRYPT_BASE64_URL_ENCODE_ERR;
        }
    }
exit:
    return ret;
}
Exemplo n.º 3
0
/*
 * Parse the public key used for signing.
 */
static int
bootutil_parse_eckey(mbedtls_ecdsa_context *ctx, uint8_t **p, uint8_t *end)
{
    size_t len;
    mbedtls_asn1_buf alg;
    mbedtls_asn1_buf param;

    if (mbedtls_asn1_get_tag(p, end, &len,
        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
        return -1;
    }
    end = *p + len;

    if (mbedtls_asn1_get_alg(p, end, &alg, &param)) {
        return -2;
    }
    if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
      memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
        return -3;
    }
    if (param.len != sizeof(ec_secp224r1_oid) - 1||
      memcmp(param.p, ec_secp224r1_oid, sizeof(ec_secp224r1_oid) - 1)) {
        return -4;
    }

    if (mbedtls_ecp_group_load_secp224r1(&ctx->grp)) {
        return -5;
    }

    if (mbedtls_asn1_get_bitstring_null(p, end, &len)) {
        return -6;
    }
    if (*p + len != end) {
        return -7;
    }

    if (mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, *p, end - *p)) {
        return -8;
    }

    if (mbedtls_ecp_check_pubkey(&ctx->grp, &ctx->Q)) {
        return -9;
    }
    return 0;
}
Exemplo n.º 4
0
/*
 * EC public key is an EC point
 *
 * The caller is responsible for clearing the structure upon failure if
 * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE
 * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state.
 */
static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end,
                            mbedtls_ecp_keypair *key )
{
    int ret;

    if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q,
                    (const unsigned char *) *p, end - *p ) ) == 0 )
    {
        ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q );
    }

    /*
     * We know mbedtls_ecp_point_read_binary consumed all bytes or failed
     */
    *p = (unsigned char *) end;

    return( ret );
}
Exemplo n.º 5
0
/*
 * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it.
 * WARNING: the resulting group should only be used with
 * pk_group_id_from_specified(), since its base point may not be set correctly
 * if it was encoded compressed.
 *
 *  SpecifiedECDomain ::= SEQUENCE {
 *      version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...),
 *      fieldID FieldID {{FieldTypes}},
 *      curve Curve,
 *      base ECPoint,
 *      order INTEGER,
 *      cofactor INTEGER OPTIONAL,
 *      hash HashAlgorithm OPTIONAL,
 *      ...
 *  }
 *
 * We only support prime-field as field type, and ignore hash and cofactor.
 */
static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp )
{
    int ret;
    unsigned char *p = params->p;
    const unsigned char * const end = params->p + params->len;
    const unsigned char *end_field, *end_curve;
    size_t len;
    int ver;

    /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */
    if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );

    if( ver < 1 || ver > 3 )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );

    /*
     * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field
     *       fieldType FIELD-ID.&id({IOSet}),
     *       parameters FIELD-ID.&Type({IOSet}{@fieldType})
     * }
     */
    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
        return( ret );

    end_field = p + len;

    /*
     * FIELD-ID ::= TYPE-IDENTIFIER
     * FieldTypes FIELD-ID ::= {
     *       { Prime-p IDENTIFIED BY prime-field } |
     *       { Characteristic-two IDENTIFIED BY characteristic-two-field }
     * }
     * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 }
     */
    if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 )
        return( ret );

    if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) ||
        memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 )
    {
        return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE );
    }

    p += len;

    /* Prime-p ::= INTEGER -- Field of size p. */
    if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );

    grp->pbits = mbedtls_mpi_bitlen( &grp->P );

    if( p != end_field )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );

    /*
     * Curve ::= SEQUENCE {
     *       a FieldElement,
     *       b FieldElement,
     *       seed BIT STRING OPTIONAL
     *       -- Shall be present if used in SpecifiedECDomain
     *       -- with version equal to ecdpVer2 or ecdpVer3
     * }
     */
    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
            MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
        return( ret );

    end_curve = p + len;

    /*
     * FieldElement ::= OCTET STRING
     * containing an integer in the case of a prime field
     */
    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
        ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 )
    {
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
    }

    p += len;

    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ||
        ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 )
    {
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );
    }

    p += len;

    /* Ignore seed BIT STRING OPTIONAL */
    if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 )
        p += len;

    if( p != end_curve )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT +
                MBEDTLS_ERR_ASN1_LENGTH_MISMATCH );

    /*
     * ECPoint ::= OCTET STRING
     */
    if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );

    if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G,
                                      ( const unsigned char *) p, len ) ) != 0 )
    {
        /*
         * If we can't read the point because it's compressed, cheat by
         * reading only the X coordinate and the parity bit of Y.
         */
        if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ||
            ( p[0] != 0x02 && p[0] != 0x03 ) ||
            len != mbedtls_mpi_size( &grp->P ) + 1 ||
            mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 ||
            mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 ||
            mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 )
        {
            return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
        }
    }

    p += len;

    /*
     * order INTEGER
     */
    if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 )
        return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret );

    grp->nbits = mbedtls_mpi_bitlen( &grp->N );

    /*
     * Allow optional elements by purposefully not enforcing p == end here.
     */

    return( 0 );
}
Exemplo n.º 6
0
int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
                  int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
{
    int ret = 0;
    CRYSError_t CrysRet = CRYS_OK;
    void* pHeap = NULL;
    size_t heapSize = 0;
    uint32_t key_size = 2*MAX_KEY_SIZE_IN_BYTES + 1;
    const CRYS_ECPKI_Domain_t*  pDomain =  CRYS_ECPKI_GetEcDomain ( convert_mbedtls_grp_id_to_crys_domain_id( gid ) );
    mbedtls_rand_func_container cc_rand = { f_rng, p_rng };


    if ( pDomain )
    {
        uint8_t temp_buf[ 2 * MAX_KEY_SIZE_IN_BYTES + 1 ] = {0};

        cc_ecc_ws_keygen_params_t* kgParams =  mbedtls_calloc( 1, sizeof(cc_ecc_ws_keygen_params_t) );
        if ( kgParams == NULL )
            return ( MBEDTLS_ERR_ECP_ALLOC_FAILED );

        pHeap = kgParams;
        heapSize = sizeof(cc_ecc_ws_keygen_params_t);

        CrysRet =  CRYS_ECPKI_GenKeyPair( &cc_rand, convert_mbedtls_to_cc_rand, pDomain,
                                          &kgParams->privKey, &kgParams->pubKey,
                                          &kgParams->kgTempData, NULL );
        if ( CrysRet != CRYS_OK )
        {
            ret = convert_CrysError_to_mbedtls_err( CrysRet );
            goto cleanup;
        }

        MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ctx->grp, gid ) );

        CrysRet = CRYS_ECPKI_ExportPublKey( &kgParams->pubKey, CRYS_EC_PointUncompressed, temp_buf,  &key_size );
        if ( CrysRet != CRYS_OK )
        {
            ret = convert_CrysError_to_mbedtls_err( CrysRet );
            goto cleanup;
        }

        ret = mbedtls_ecp_point_read_binary( &ctx->grp, &ctx->Q, temp_buf, key_size );
        if ( ret != 0 )
            goto cleanup;

        memset ( temp_buf, 0 , sizeof(temp_buf) );

        CrysRet = CRYS_COMMON_ConvertLswMswWordsToMsbLsbBytes( temp_buf, (ctx->grp.nbits+7)/8,
                                                               kgParams->privKey.PrivKeyDbBuff,
                                                               4*((((ctx->grp.nbits+7)/8)+3)/4) );
        if ( CrysRet != CRYS_OK )
        {
            ret = convert_CrysError_to_mbedtls_err( CrysRet );
            mbedtls_zeroize( temp_buf, sizeof(temp_buf) );
            goto cleanup;
        }

        ret = mbedtls_mpi_read_binary( &ctx->d, temp_buf, (ctx->grp.nbits+7)/8 );
        mbedtls_zeroize( temp_buf, sizeof(temp_buf) );
        if ( ret != 0 )
        {
            goto cleanup;
        }
    }
    else
        ret =  MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;


cleanup:
    if ( pHeap )
    {
        mbedtls_zeroize( pHeap, heapSize );
        mbedtls_free ( pHeap );
    }
    return ( ret );
}
Exemplo n.º 7
0
bool ECKey_From(const cn_cbor * pKey, mbedtls_ecp_keypair *keypair, cose_errback * perr)
{
	byte  rgbKey[MBEDTLS_ECP_MAX_PT_LEN];
	int cbKey;
	int cbGroup;
	const cn_cbor * p;
	mbedtls_ecp_group_id groupId;

	p = cn_cbor_mapget_int(pKey, COSE_Key_Type);
	CHECK_CONDITION(p != NULL, COSE_ERR_INVALID_PARAMETER);
	if(p->type == CN_CBOR_UINT) {
		CHECK_CONDITION(p->v.uint == COSE_Key_Type_EC2, COSE_ERR_INVALID_PARAMETER);
	}
	else {
		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
	}

	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Curve);
	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_UINT), COSE_ERR_INVALID_PARAMETER);

	switch (p->v.uint) {
	case 1: // P-256
		groupId = MBEDTLS_ECP_DP_SECP256R1;
		break;

	case 2: // P-384
		groupId = MBEDTLS_ECP_DP_SECP384R1;
		break;

	case 3: // P-521
		groupId = MBEDTLS_ECP_DP_SECP521R1;
		break;

	default:
		FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);
	}
	CHECK_CONDITION(mbedtls_ecp_group_load(&keypair->grp, groupId) == 0, COSE_ERR_INVALID_PARAMETER);
	cbGroup = (keypair->grp.nbits + 7) / 8;

	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_X);
	CHECK_CONDITION((p != NULL) && (p->type == CN_CBOR_BYTES), COSE_ERR_INVALID_PARAMETER);
	CHECK_CONDITION(p->length == cbGroup, COSE_ERR_INVALID_PARAMETER);
	memcpy(rgbKey+1, p->v.str, p->length);
	

	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_Y);
	CHECK_CONDITION((p != NULL), COSE_ERR_INVALID_PARAMETER);
	if (p->type == CN_CBOR_BYTES) {
		rgbKey[0] = 0x04;
		cbKey = cbGroup * 2 + 1;
		CHECK_CONDITION(p->length == cbGroup, COSE_ERR_INVALID_PARAMETER);
		memcpy(rgbKey + p->length + 1, p->v.str, p->length);
	}
	else if (p->type == CN_CBOR_TRUE) {
		cbKey = cbGroup + 1;
		rgbKey[0] = 0x03;
	}
	else if (p->type == CN_CBOR_FALSE) {
		cbKey = cbGroup + 1;
		rgbKey[0] = 0x02;
	}
	else FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER);

	CHECK_CONDITION(mbedtls_ecp_point_read_binary(&keypair->grp, &keypair->Q, rgbKey, cbKey) == 0, COSE_ERR_INVALID_PARAMETER);

	p = cn_cbor_mapget_int(pKey, COSE_Key_EC_d);
	if (p != NULL) {
		CHECK_CONDITION(p->type == CN_CBOR_BYTES, COSE_ERR_INVALID_PARAMETER);
		CHECK_CONDITION(mbedtls_mpi_read_binary( &keypair->d, p->v.bytes, p->length) == 0, COSE_ERR_CRYPTO_FAIL);
	}
	return true;

errorReturn:
	return false;
}
Exemplo n.º 8
0
int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q,
                     int ( *f_rng )( void *, unsigned char *, size_t ),
                     void *p_rng )
{
      int ret = 0;
      void* pHeap = NULL;
      size_t   heapSize = 0;

      uint32_t public_key_size = (2 * MAX_KEY_SIZE_IN_BYTES + 1);
      const CRYS_ECPKI_Domain_t*  pDomain =  CRYS_ECPKI_GetEcDomain ( convert_mbedtls_grp_id_to_crys_domain_id(  grp->id ) );
      mbedtls_rand_func_container cc_rand = { f_rng, p_rng };

      if ( pDomain )
      {
          uint8_t temp_buf[ 2 * MAX_KEY_SIZE_IN_BYTES + 1 ] = {0};
          cc_ecc_ws_keygen_params_t* kgParams =  mbedtls_calloc( 1, sizeof( cc_ecc_ws_keygen_params_t ) );

          if ( kgParams == NULL )
              return ( MBEDTLS_ERR_ECP_ALLOC_FAILED );
          pHeap = kgParams;
          heapSize = sizeof( cc_ecc_ws_keygen_params_t );

          ret = convert_CrysError_to_mbedtls_err( CRYS_ECPKI_GenKeyPair( &cc_rand, convert_mbedtls_to_cc_rand,
                                       pDomain, &kgParams->privKey,
                                       &kgParams->pubKey,
                                       &kgParams->kgTempData, NULL ) );
          if( ret != 0 )
          {
              goto cleanup;
          }

          ret = convert_CrysError_to_mbedtls_err( CRYS_ECPKI_ExportPublKey( &kgParams->pubKey,
                                         CRYS_EC_PointUncompressed,temp_buf,  &public_key_size ) );
          if( ret != 0 )
          {
              goto cleanup;
          }


          MBEDTLS_MPI_CHK( mbedtls_ecp_point_read_binary( grp, Q, temp_buf, public_key_size ) );
          memset ( temp_buf, 0 , sizeof(temp_buf) );

          ret = convert_CrysError_to_mbedtls_err( CRYS_COMMON_ConvertLswMswWordsToMsbLsbBytes( temp_buf, (grp->nbits+7)/8,
                                                            kgParams->privKey.PrivKeyDbBuff,
                                                            4*((((grp->nbits+7)/8)+3)/4) ) );
          if( ret != 0 )
          {
              mbedtls_zeroize( temp_buf, sizeof( temp_buf ) );
              goto cleanup;
          }

          MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary( d, temp_buf, (grp->nbits+7)/8 ) );
          mbedtls_zeroize( temp_buf, sizeof( temp_buf ) );
      }

      /* if CRYS_ECPKI_GetEcDomain returns NULL, then the given curve is either Montgomery 25519
       * or another curve which is not supported by CC310*/
      else if ( grp->id ==  MBEDTLS_ECP_DP_CURVE25519 )
      {
          size_t priv_key_size =  public_key_size = CURVE_25519_KEY_SIZE ;

          cc_ecc_25519_keygen_params_t* kgParams =  mbedtls_calloc( 1, sizeof(cc_ecc_25519_keygen_params_t) );

          if ( kgParams == NULL )
              return ( MBEDTLS_ERR_ECP_ALLOC_FAILED );
          pHeap = ( uint8_t* )kgParams;
          heapSize = sizeof(cc_ecc_25519_keygen_params_t);

          ret = convert_CrysError_to_mbedtls_err( CRYS_ECMONT_KeyPair( kgParams->pubKey, ( size_t* )&public_key_size, kgParams->privKey,
                                    &priv_key_size, &cc_rand, convert_mbedtls_to_cc_rand,
                                    &kgParams->kgTempData ) );
          if( ret != 0 )
          {
              goto cleanup;
          }

          MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( d, kgParams->privKey, priv_key_size ) );
          MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(  &Q->X, kgParams->pubKey, public_key_size ) );
          MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Q->Z, 1 ) );
      }
      else
          ret =  MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED;

cleanup:

    if ( pHeap )
    {
        mbedtls_zeroize( pHeap, heapSize );
        mbedtls_free( pHeap );
    }

    return ( ret );
}