static AJ_Status DecodeCertificateSig(DER_Element* der, ecc_signature* signature) { AJ_Status status; DER_Element seq; DER_Element int1; DER_Element int2; uint8_t tags[] = { ASN_INTEGER, ASN_INTEGER }; status = AJ_ASN1DecodeElement(der, ASN_SEQ, &seq); if (AJ_OK != status) { return status; } status = AJ_ASN1DecodeElements(&seq, tags, sizeof (tags), &int1, &int2); if (AJ_OK != status) { return status; } /* * Skip over unused bits. */ if ((0 < int1.size) && (0 == *int1.data)) { int1.data++; int1.size--; } if ((0 < int2.size) && (0 == *int2.data)) { int2.data++; int2.size--; } memset(signature, 0, sizeof (ecc_signature)); AJ_BigvalDecode(int1.data, &signature->r, int1.size); AJ_BigvalDecode(int2.data, &signature->s, int2.size); return status; }
static AJ_Status DecodeCertificatePub(DER_Element* der, AJ_KeyInfo* keyinfo) { AJ_Status status; DER_Element seq; DER_Element bit; DER_Element oid1; DER_Element oid2; uint8_t tags1[] = { ASN_SEQ, ASN_BITS }; uint8_t tags2[] = { ASN_OID, ASN_OID }; status = AJ_ASN1DecodeElements(der, tags1, sizeof (tags1), &seq, &bit); if (AJ_OK != status) { return status; } /* * We only accept NISTP256 ECC keys at the moment. */ status = AJ_ASN1DecodeElements(&seq, tags2, sizeof (tags2), &oid1, &oid2); if (AJ_OK != status) { return status; } if (sizeof (OID_KEY_ECC) != oid1.size) { return AJ_ERR_INVALID; } if (0 != memcmp(OID_KEY_ECC, oid1.data, oid1.size)) { return AJ_ERR_INVALID; } if (sizeof (OID_CRV_PRIME256V1) != oid2.size) { return AJ_ERR_INVALID; } if (0 != memcmp(OID_CRV_PRIME256V1, oid2.data, oid2.size)) { return AJ_ERR_INVALID; } /* * We only accept uncompressed ECC points. */ if ((2 + KEY_ECC_PUB_SZ) != bit.size) { return AJ_ERR_INVALID; } if ((0x00 != bit.data[0]) || (0x04 != bit.data[1])) { return AJ_ERR_INVALID; } bit.data += 2; bit.size -= 2; memset(keyinfo, 0, sizeof (AJ_KeyInfo)); keyinfo->fmt = KEY_FMT_ALLJOYN; keyinfo->use = KEY_USE_SIG; keyinfo->kty = KEY_TYP_ECC; keyinfo->alg = KEY_ALG_ECDSA_SHA256; keyinfo->crv = KEY_CRV_NISTP256; AJ_BigvalDecode(bit.data, &keyinfo->key.publickey.x, KEY_ECC_SZ); bit.data += KEY_ECC_SZ; bit.size -= KEY_ECC_SZ; AJ_BigvalDecode(bit.data, &keyinfo->key.publickey.y, KEY_ECC_SZ); return status; }
static AJ_Status DecodeCertificatePub(ecc_publickey* pub, DER_Element* der) { AJ_Status status; DER_Element seq; DER_Element bit; DER_Element oid1; DER_Element oid2; const uint8_t tags1[] = { ASN_SEQ, ASN_BITS }; const uint8_t tags2[] = { ASN_OID, ASN_OID }; memset(pub, 0, sizeof (ecc_publickey)); status = AJ_ASN1DecodeElements(der, tags1, sizeof (tags1), &seq, &bit); if (AJ_OK != status) { return status; } /* * We only accept NISTP256 ECC keys at the moment. */ status = AJ_ASN1DecodeElements(&seq, tags2, sizeof (tags2), &oid1, &oid2); if (AJ_OK != status) { return status; } if (!CompareOID(&oid1, OID_KEY_ECC, sizeof (OID_KEY_ECC))) { return AJ_ERR_INVALID; } if (!CompareOID(&oid2, OID_CRV_PRIME256V1, sizeof (OID_CRV_PRIME256V1))) { return AJ_ERR_INVALID; } /* * We only accept uncompressed ECC points. */ if ((2 + KEY_ECC_PUB_SZ) != bit.size) { return AJ_ERR_INVALID; } if ((0x00 != bit.data[0]) || (0x04 != bit.data[1])) { return AJ_ERR_INVALID; } bit.data += 2; bit.size -= 2; AJ_BigvalDecode(bit.data, &pub->x, KEY_ECC_SZ); bit.data += KEY_ECC_SZ; bit.size -= KEY_ECC_SZ; AJ_BigvalDecode(bit.data, &pub->y, KEY_ECC_SZ); return status; }
AJ_Status AJ_DecodePrivateKeyDER(ecc_privatekey* key, DER_Element* der) { AJ_Status status; DER_Element seq; DER_Element ver; DER_Element prv; DER_Element alg; const uint8_t tags1[] = { ASN_SEQ }; const uint8_t tags2[] = { ASN_INTEGER, ASN_OCTETS, ASN_CONTEXT_SPECIFIC }; status = AJ_ASN1DecodeElements(der, tags1, sizeof (tags1), &seq); if (AJ_OK != status) { return status; } status = AJ_ASN1DecodeElements(&seq, tags2, sizeof (tags2), &ver, &prv, 0, &alg); if (AJ_OK != status) { return status; } if ((1 != ver.size) || (1 != *ver.data)) { return AJ_ERR_INVALID; } if (KEY_ECC_PRV_SZ != prv.size) { return AJ_ERR_INVALID; } AJ_BigvalDecode(prv.data, key, KEY_ECC_SZ); return status; }