in core/asn1/ecc_der_util.c [608:715]
int ecc_der_decode_public_key_no_copy (const uint8_t *der, size_t length, const uint8_t **pub_key)
{
const uint8_t *pos = der;
size_t type_len;
size_t oid_len;
size_t key_len;
const uint8_t *oid;
int status;
if ((der == NULL) || (pub_key == NULL)) {
return ECC_DER_UTIL_INVALID_ARGUMENT;
}
status = ecc_der_get_next_tag (0x30, &pos, &length, &type_len);
if (status != 0) {
return status;
}
status = ecc_der_get_next_tag (0x30, &pos, &length, &type_len);
if (status != 0) {
return status;
}
status = ecc_der_get_next_tag (0x06, &pos, &length, &type_len);
if (status != 0) {
return status;
}
if (((type_len != sizeof (ECC_DER_EC_PUBLIC_KEY_OID)) ||
(memcmp (pos, ECC_DER_EC_PUBLIC_KEY_OID, type_len) != 0))) {
return ECC_DER_UTIL_UNSUPPORTED_ALGORITHM;
}
pos += type_len;
length -= type_len;
status = ecc_der_get_next_tag (0x06, &pos, &length, &type_len);
if (status != 0) {
return status;
}
/* Save the curve OID so we can compare against it once we know the key length. */
oid_len = type_len;
oid = pos;
pos += type_len;
length -= type_len;
status = ecc_der_get_next_tag (0x03, &pos, &length, &type_len);
if (status != 0) {
return status;
}
key_len = (type_len - 2) / 2;
switch (key_len) {
case ECC_KEY_LENGTH_256:
if ((oid_len != sizeof (ECC_DER_P256_OID)) ||
(memcmp (oid, ECC_DER_P256_OID, oid_len) != 0)) {
return ECC_DER_UTIL_UNSUPPORTED_CURVE;
}
break;
#if ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_384
case ECC_KEY_LENGTH_384:
if ((oid_len != sizeof (ECC_DER_P384_OID)) ||
(memcmp (oid, ECC_DER_P384_OID, oid_len) != 0)) {
return ECC_DER_UTIL_UNSUPPORTED_CURVE;
}
break;
#endif
#if ECC_MAX_KEY_LENGTH >= ECC_KEY_LENGTH_521
case ECC_KEY_LENGTH_521:
if ((oid_len != sizeof (ECC_DER_P521_OID)) ||
(memcmp (oid, ECC_DER_P521_OID, oid_len) != 0)) {
return ECC_DER_UTIL_UNSUPPORTED_CURVE;
}
break;
#endif
default:
return ECC_DER_UTIL_UNSUPPORTED_KEY_LENGTH;
}
/* Skip over the leading zero in the public key bit string. */
pos++;
type_len--;
/* Confirm a valid ECPoint format for the public key. */
switch (pos[0]) {
case 0x02:
case 0x03:
/* Compressed ECPoint */
break;
case 0x04:
/* Uncompressed ECPoint */
break;
default:
return ECC_DER_UTIL_INVALID_ECPOINT;
}
*pub_key = pos;
return type_len;
}