core/riot/reference/RiotX509Bldr.c (551 lines of code) (raw):

/* * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See LICENSE in the project root. */ #include <stdbool.h> #include <stdint.h> #include "include/RiotDerDec.h" #include "include/RiotDerEnc.h" #include "include/RiotX509Bldr.h" #include "riot/tcg_dice.h" #define ASRT(_X) if(!(_X)) {goto Error;} #define CHK(_X) if(((_X)) < 0) {goto Error;} // OIDs. Note that the encoder expects a -1 sentinel. const int riotOID[] = {1, 3, 6, 1, 4, 1, 311, 89, 3, 1, -1}; const int ecdsaWithSHA256OID[] = {1, 2, 840, 10045, 4, 3, 2, -1}; const int ecdsaWithSHA384OID[] = {1, 2, 840, 10045, 4, 3, 3, -1}; const int ecdsaWithSHA512OID[] = {1, 2, 840, 10045, 4, 3, 4, -1}; const int ecPublicKeyOID[] = {1, 2, 840, 10045, 2, 1, -1}; const int prime256v1OID[] = {1, 2, 840, 10045, 3, 1, 7, -1}; const int keyUsageOID[] = {2, 5, 29, 15, -1}; const int extKeyUsageOID[] = {2, 5, 29, 37, -1}; const int extAuthKeyIdentifierOID[] = {2, 5, 29, 35, -1}; const int extSubjectKeyIdentifierOID[] = {2, 5, 29, 14, -1}; const int clientAuthOID[] = {1, 3, 6, 1, 5, 5, 7, 3, 2, -1}; const int sha1OID[] = {1, 3, 14, 3, 2, 26, -1}; const int sha256OID[] = {2, 16, 840, 1, 101, 3, 4, 2, 1, -1}; const int sha384OID[] = {2, 16, 840, 1, 101, 3, 4, 2, 2, -1}; const int sha512OID[] = {2, 16, 840, 1, 101, 3, 4, 2, 3, -1}; const int commonNameOID[] = {2, 5, 4, 3, -1}; const int countryNameOID[] = {2, 5, 4, 6, -1}; const int orgNameOID[] = {2, 5, 4, 10, -1}; const int basicConstraintsOID[] = {2, 5, 29, 19, -1}; const int extensionRequestOID[] = {1, 2, 840, 113549, 1, 9, 14, -1}; const int tcbInfoOID[] = {2, 23, 133, 5, 4, 1, -1}; const int ueidOID[] = {2, 23, 133, 5, 4, 4, -1}; static int GenerateGuidFromSeed (char *nameBuf, size_t *nameBufLen, const uint8_t *seed, size_t seedLen, const struct hash_engine *hash, const struct base64_engine *base64) { uint8_t digest[SHA256_DIGEST_LENGTH]; int result; result = hash->calculate_sha256 (hash, seed, seedLen, digest, sizeof (digest)); if (result != 0) { return -1; } result = base64->encode (base64, digest, 16, (unsigned char*) nameBuf, *nameBufLen); if (result != 0) { return -1; } return 0; } static int X509AddKeyUsageExtension ( DERBuilderContext *Tbs, int Type) { uint8_t keyUsage; uint8_t bits; if (Type) { keyUsage = RIOT_X509_KEY_USAGE_CERT_SIGN; bits = 6; } else { keyUsage = RIOT_X509_KEY_USAGE_END_ENTITY; bits = 5; } CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, keyUsageOID)); CHK (DERAddBoolean (Tbs, true)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERAddNamedBitString (Tbs, &keyUsage, 1, bits)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); return 0; Error: return -1; } static int X509AddExtendedKeyUsageExtension ( DERBuilderContext *Tbs, int Type, const uint8_t *Oid, size_t OidLength) { if (Type == X509_CERT_END_ENTITY) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, extKeyUsageOID)); CHK (DERAddBoolean (Tbs, true)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, clientAuthOID)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); } else if (Oid != NULL) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, extKeyUsageOID)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddEncodedOID (Tbs, Oid, OidLength)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); } return 0; Error: return -1; } static int X509AddBasicConstraintsExtension ( DERBuilderContext *Tbs, int Type) { if (Type) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, basicConstraintsOID)); CHK (DERAddBoolean (Tbs, true)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddBoolean (Tbs, true)); if (Type < X509_CERT_CA_NO_PATHLEN) { CHK (DERAddInteger (Tbs, Type - 1)); } CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); } return 0; Error: return -1; } static int X509AddRiotExtension ( DERBuilderContext *Tbs, const uint8_t *DevIdPub, size_t DevIdPubLen, const uint8_t *Fwid, size_t FwidLen, const int *shaOID) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, riotOID)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddInteger (Tbs, 1)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, ecPublicKeyOID)); CHK (DERAddOID (Tbs, prime256v1OID)); CHK (DERPopNesting (Tbs)); CHK (DERAddBitString (Tbs, DevIdPub, DevIdPubLen)); CHK (DERPopNesting (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, shaOID)); CHK (DERAddOctetString (Tbs, Fwid, FwidLen)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); return 0; Error: return -1; } static int X509AddTcbInfoExtension ( DERBuilderContext *Tbs, const struct tcg_dice_tcbinfo *Tcb, const int *shaOID, size_t FwidLen) { if (Tcb) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, tcbInfoOID)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddString (Tbs, Tcb->version, 0x82)); CHK (DERAddTaggedIntegerFromArray (Tbs, Tcb->svn, Tcb->svn_length, 0x83)); CHK (DERStartConstructed (Tbs, 0xA6)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, shaOID)); CHK (DERAddOctetString (Tbs, Tcb->fwid, FwidLen)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); } return 0; Error: return -1; } static int X509AddSubjectKeyIdentifierExtension ( DERBuilderContext *Tbs, const uint8_t *subjectKeyIdentifier) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, extSubjectKeyIdentifierOID)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERAddOctetString (Tbs, subjectKeyIdentifier, SHA1_DIGEST_LENGTH)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); return 0; Error: return -1; } static int X509AddAuthorityKeyIdentifierExtension ( DERBuilderContext *Tbs, const uint8_t *authKeyIdentifier) { CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, extAuthKeyIdentifierOID)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddAuthKeyBitString (Tbs, authKeyIdentifier, SHA1_DIGEST_LENGTH)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); return 0; Error: return -1; } static int X509AddX501Name ( DERBuilderContext *Context, const char *CommonName, const char *OrgName, const char *CountryName) { CHK (DERStartSequenceOrSet (Context, true)); if (CommonName) { CHK (DERStartSequenceOrSet (Context, false)); CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddOID (Context, commonNameOID)); CHK (DERAddUTF8String (Context, CommonName)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); } if (CountryName) { CHK (DERStartSequenceOrSet (Context, false)); CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddOID (Context, countryNameOID)); CHK (DERAddUTF8String (Context, CountryName)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); } if (OrgName) { CHK (DERStartSequenceOrSet (Context, false)); CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddOID (Context, orgNameOID)); CHK (DERAddUTF8String (Context, OrgName)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); } CHK (DERPopNesting (Context)); return 0; Error: return -1; } int X509GetDeviceCertTBS ( DERBuilderContext *Tbs, const RIOT_X509_TBS_DATA *TbsData, const uint8_t *CertKey, size_t CertKeyLen, const uint8_t *SubjectKeyIdentifier, const uint8_t *AuthKeyIdentifier, int Type, const struct tcg_dice_tcbinfo *Dice) { const int *sha_oid = NULL; size_t fw_id_len = 0; // DEPRECATED // if (Dice) { // if (Dice->version == NULL) { // return X509_ENGINE_DICE_NO_VERSION; // } // status = get_fw_id_info(&fw_id_len, &sha_oid, Dice->fw_id, Dice->fw_id_hash); // if (status != 0) { // return status; // } // if (Dice->ueid && ((Dice->ueid->ueid == NULL) || (Dice->ueid->length == 0))) { // return X509_ENGINE_DICE_NO_UEID; // } // } CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddShortExplicitInteger (Tbs, 2)); CHK (DERAddIntegerFromArray (Tbs, TbsData->SerialNum, TbsData->SerialLen)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, TbsData->SignatureAlgorithm)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->IssuerCommon, NULL, NULL)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddTime (Tbs, TbsData->ValidFrom)); CHK (DERAddTime (Tbs, TbsData->ValidTo)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->SubjectCommon, NULL, NULL)); CHK (DERAddPublicKey (Tbs, CertKey, CertKeyLen)); CHK (DERStartExplicit (Tbs, 3)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (X509AddSubjectKeyIdentifierExtension (Tbs, SubjectKeyIdentifier)); CHK (X509AddAuthorityKeyIdentifierExtension (Tbs, AuthKeyIdentifier)); CHK (X509AddKeyUsageExtension (Tbs, Type)); CHK (X509AddExtendedKeyUsageExtension (Tbs, Type, NULL, 0)); CHK (X509AddBasicConstraintsExtension (Tbs, Type)); CHK (X509AddTcbInfoExtension (Tbs, Dice, sha_oid, fw_id_len)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); ASRT (DERGetNestingDepth (Tbs) == 0); return 0; Error: return -1; } int X509MakeDeviceCert ( DERBuilderContext *DeviceIDCert, const uint8_t *TbsSig, size_t SigLength, const int *SigOID) // Create a Device Certificate given a ready-to-sign TBS region in the context { // Elevate the "TBS" block into a real certificate, // i.e., copy it into an enclosing sequence. CHK (DERTbsToCert (DeviceIDCert)); CHK (DERStartSequenceOrSet (DeviceIDCert, true)); CHK (DERAddOID (DeviceIDCert, SigOID)); CHK (DERPopNesting (DeviceIDCert)); CHK (DERAddBitString (DeviceIDCert, TbsSig, SigLength)); CHK (DERPopNesting (DeviceIDCert)); ASRT (DERGetNestingDepth (DeviceIDCert) == 0); return 0; Error: return -1; } int X509GetCASignedCertTBS ( DERBuilderContext *Tbs, const RIOT_X509_TBS_DATA *TbsData, const uint8_t *CertKey, size_t CertKeyLen, const uint8_t *SubjectKeyIdentifier, const uint8_t *AuthKeyIdentifier, int Type, const struct tcg_dice_tcbinfo *Dice) { const int *sha_oid = NULL; size_t fw_id_len = 0; // DEPRECATED // if (dice) { // if (dice->version == NULL) { // return X509_ENGINE_DICE_NO_VERSION; // } // status = get_fw_id_info (&fw_id_len, &sha_oid, dice->fw_id, dice->fw_id_hash); // if (status != 0) { // return status; // } // if (dice->ueid && ((dice->ueid->ueid == NULL) || (dice->ueid->length == 0))) { // return X509_ENGINE_DICE_NO_UEID; // } // } CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddShortExplicitInteger (Tbs, 2)); CHK (DERAddIntegerFromArray (Tbs, TbsData->SerialNum, TbsData->SerialLen)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, TbsData->SignatureAlgorithm)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->IssuerCommon, NULL, NULL)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddTime (Tbs, TbsData->ValidFrom)); CHK (DERAddTime (Tbs, TbsData->ValidTo)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->SubjectCommon, NULL, NULL)); CHK (DERAddPublicKey (Tbs, CertKey, CertKeyLen)); CHK (DERStartExplicit (Tbs, 3)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (X509AddSubjectKeyIdentifierExtension (Tbs, SubjectKeyIdentifier)); CHK (X509AddAuthorityKeyIdentifierExtension (Tbs, AuthKeyIdentifier)); CHK (X509AddKeyUsageExtension (Tbs, Type)); CHK (X509AddExtendedKeyUsageExtension (Tbs, Type, NULL, 0)); CHK (X509AddBasicConstraintsExtension (Tbs, Type)); CHK (X509AddTcbInfoExtension (Tbs, Dice, sha_oid, fw_id_len)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); ASRT (DERGetNestingDepth (Tbs) == 0); return 0; Error: return -1; } int X509GetAliasCertTBS ( DERBuilderContext *Tbs, RIOT_X509_TBS_DATA *TbsData, RIOT_ECC_PUBLIC *AliasKeyPub, RIOT_ECC_PUBLIC *DevIdKeyPub, uint8_t *Fwid, size_t FwidLen, int type, const struct hash_engine *hash, const struct base64_engine *base64) { int result; char guidBuffer[64]; uint8_t encBuffer[65]; size_t encBufferLen; uint8_t authKeyIdentifier[SHA1_DIGEST_LENGTH]; int status; if (strcmp (TbsData->SubjectCommon, "*") == 0) { RiotCrypt_ExportEccPub (DevIdKeyPub, encBuffer, &encBufferLen); size_t bufLen = sizeof (guidBuffer); // Replace the common-name with a per-device GUID derived from the DeviceID public key result = GenerateGuidFromSeed (guidBuffer, &bufLen, encBuffer, encBufferLen, hash, base64); if (result < 0) { return result; } guidBuffer[bufLen - 1] = 0; TbsData->SubjectCommon = guidBuffer; } CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddShortExplicitInteger (Tbs, 2)); CHK (DERAddIntegerFromArray (Tbs, TbsData->SerialNum, TbsData->SerialLen)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, ecdsaWithSHA256OID)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->IssuerCommon, TbsData->IssuerOrg, TbsData->IssuerCountry)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddTime (Tbs, TbsData->ValidFrom)); CHK (DERAddTime (Tbs, TbsData->ValidTo)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->SubjectCommon, TbsData->SubjectOrg, TbsData->SubjectCountry)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, ecPublicKeyOID)); CHK (DERAddOID (Tbs, prime256v1OID)); CHK (DERPopNesting (Tbs)); RiotCrypt_ExportEccPub (AliasKeyPub, encBuffer, &encBufferLen); CHK (DERAddBitString (Tbs, encBuffer, encBufferLen)); CHK (DERPopNesting (Tbs)); RiotCrypt_ExportEccPub (DevIdKeyPub, encBuffer, &encBufferLen); status = hash->calculate_sha1 (hash, encBuffer, encBufferLen, authKeyIdentifier, SHA1_DIGEST_LENGTH); ASRT (status == 0); CHK (DERStartExplicit (Tbs, 3)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (X509AddKeyUsageExtension (Tbs, type)); CHK (X509AddExtendedKeyUsageExtension (Tbs, type, NULL, 0)); CHK (X509AddAuthorityKeyIdentifierExtension (Tbs, authKeyIdentifier)); CHK (X509AddRiotExtension (Tbs, encBuffer, encBufferLen, Fwid, FwidLen, sha256OID)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); ASRT (DERGetNestingDepth (Tbs) == 0); return 0; Error: return -1; } int X509MakeAliasCert ( DERBuilderContext *AliasCert, RIOT_ECC_SIGNATURE *TbsSig) // Create an Alias Certificate given a ready-to-sign TBS region in the context { uint8_t encBuffer[((BIGLEN - 1) * 4)]; size_t encBufferLen = ((BIGLEN - 1) * 4); // Elevate the "TBS" block into a real certificate, // i.e., copy it into an enclosing sequence. CHK (DERTbsToCert (AliasCert)); CHK (DERStartSequenceOrSet (AliasCert, true)); CHK (DERAddOID (AliasCert, ecdsaWithSHA256OID)); CHK (DERPopNesting (AliasCert)); CHK (DERStartEnvelopingBitString (AliasCert)); CHK (DERStartSequenceOrSet (AliasCert, true)); BigValToBigInt (encBuffer, &TbsSig->r); CHK (DERAddIntegerFromArray (AliasCert, encBuffer, encBufferLen)); BigValToBigInt (encBuffer, &TbsSig->s); CHK (DERAddIntegerFromArray (AliasCert, encBuffer, encBufferLen)); CHK (DERPopNesting (AliasCert)); CHK (DERPopNesting (AliasCert)); CHK (DERPopNesting (AliasCert)); ASRT (DERGetNestingDepth (AliasCert) == 0); return 0; Error: return -1; } int X509GetDEREccPub ( DERBuilderContext *Context, RIOT_ECC_PUBLIC Pub) { uint8_t encBuffer[65]; size_t encBufferLen; CHK (DERStartSequenceOrSet (Context, true)); CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddOID (Context, ecPublicKeyOID)); CHK (DERAddOID (Context, prime256v1OID)); CHK (DERPopNesting (Context)); RiotCrypt_ExportEccPub (&Pub, encBuffer, &encBufferLen); CHK (DERAddBitString (Context, encBuffer, encBufferLen)); CHK (DERPopNesting (Context)); ASRT (DERGetNestingDepth (Context) == 0); return 0; Error: return -1; } int X509GetDEREcc ( DERBuilderContext *Context, RIOT_ECC_PUBLIC Pub, RIOT_ECC_PRIVATE Priv) { uint8_t encBuffer[65]; size_t encBufferLen; CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddInteger (Context, 1)); BigValToBigInt (encBuffer, &Priv); CHK (DERAddOctetString (Context, encBuffer, 32)); CHK (DERStartExplicit (Context, 0)); CHK (DERAddOID (Context, prime256v1OID)); CHK (DERPopNesting (Context)); CHK (DERStartExplicit (Context, 1)); RiotCrypt_ExportEccPub (&Pub, encBuffer, &encBufferLen); CHK (DERAddBitString (Context, encBuffer, encBufferLen)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); ASRT (DERGetNestingDepth (Context) == 0); return 0; Error: return -1; } int X509GetDERCsrTbs ( DERBuilderContext *Context, RIOT_X509_TBS_DATA *TbsData, uint8_t *DeviceIDPub, size_t key_len, int type, const uint8_t *oid, size_t oid_len, const struct tcg_dice_tcbinfo *dice) { const int *sha_oid = NULL; size_t fw_id_len = 0; // DEPRECATED // if (dice) { // if (dice->version == NULL) { // return X509_ENGINE_DICE_NO_VERSION; // } // status = get_fw_id_info (&fw_id_len, &sha_oid, dice->fw_id, dice->fw_id_hash); // if (status != 0) { // return status; // } // if (dice->ueid && ((dice->ueid->ueid == NULL) || (dice->ueid->length == 0))) { // return X509_ENGINE_DICE_NO_UEID; // } // } CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddInteger (Context, 0)); CHK (X509AddX501Name (Context, TbsData->IssuerCommon, NULL, NULL)); CHK (DERAddPublicKey (Context, DeviceIDPub, key_len)); CHK (DERStartExplicit (Context, 0)); CHK (DERStartSequenceOrSet (Context, true)); CHK (DERAddOID (Context, extensionRequestOID)); CHK (DERStartSequenceOrSet (Context, false)); CHK (DERStartSequenceOrSet (Context, true)); CHK (X509AddKeyUsageExtension (Context, type)); CHK (X509AddExtendedKeyUsageExtension (Context, type, oid, oid_len)); CHK (X509AddBasicConstraintsExtension (Context, type)); CHK (X509AddTcbInfoExtension (Context, dice, sha_oid, fw_id_len)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); CHK (DERPopNesting (Context)); ASRT (DERGetNestingDepth (Context) == 0); return 0; Error: return -1; } int X509GetDERCsr ( DERBuilderContext *Context, const uint8_t *Signature, size_t SigLength, const int *SigOID) { return X509MakeDeviceCert (Context, Signature, SigLength, SigOID); } int X509GetRootCertTBS ( DERBuilderContext *Tbs, RIOT_X509_TBS_DATA *TbsData, RIOT_ECC_PUBLIC *RootKeyPub) { uint8_t encBuffer[65]; size_t encBufferLen; uint8_t keyUsage = RIOT_X509_KEY_USAGE_CERT_SIGN; CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddShortExplicitInteger (Tbs, 2)); CHK (DERAddIntegerFromArray (Tbs, TbsData->SerialNum, TbsData->SerialLen)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, ecdsaWithSHA256OID)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->IssuerCommon, TbsData->IssuerOrg, TbsData->IssuerCountry)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddTime (Tbs, TbsData->ValidFrom)); CHK (DERAddTime (Tbs, TbsData->ValidTo)); CHK (DERPopNesting (Tbs)); CHK (X509AddX501Name (Tbs, TbsData->SubjectCommon, TbsData->SubjectOrg, TbsData->SubjectCountry)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, ecPublicKeyOID)); CHK (DERAddOID (Tbs, prime256v1OID)); CHK (DERPopNesting (Tbs)); RiotCrypt_ExportEccPub (RootKeyPub, encBuffer, &encBufferLen); CHK (DERAddBitString (Tbs, encBuffer, encBufferLen)); CHK (DERPopNesting (Tbs)); CHK (DERStartExplicit (Tbs, 3)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, keyUsageOID)); CHK (DERStartEnvelopingOctetString (Tbs)); encBufferLen = 1; CHK (DERAddBitString (Tbs, &keyUsage, encBufferLen)); // Actually 6bits CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddOID (Tbs, basicConstraintsOID)); CHK (DERAddBoolean (Tbs, true)); CHK (DERStartEnvelopingOctetString (Tbs)); CHK (DERStartSequenceOrSet (Tbs, true)); CHK (DERAddBoolean (Tbs, true)); CHK (DERAddInteger (Tbs, 2)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); CHK (DERPopNesting (Tbs)); ASRT (DERGetNestingDepth (Tbs) == 0); return 0; Error: return -1; } int X509MakeRootCert ( DERBuilderContext *RootCert, RIOT_ECC_SIGNATURE *TbsSig) // Create an Alias Certificate given a ready-to-sign TBS region in the context { uint8_t encBuffer[((BIGLEN - 1) * 4)]; size_t encBufferLen = ((BIGLEN - 1) * 4); // Elevate the "TBS" block into a real certificate, // i.e., copy it into an enclosing sequence. CHK (DERTbsToCert (RootCert)); CHK (DERStartSequenceOrSet (RootCert, true)); CHK (DERAddOID (RootCert, ecdsaWithSHA256OID)); CHK (DERPopNesting (RootCert)); CHK (DERStartEnvelopingBitString (RootCert)); CHK (DERStartSequenceOrSet (RootCert, true)); BigValToBigInt (encBuffer, &TbsSig->r); CHK (DERAddIntegerFromArray (RootCert, encBuffer, encBufferLen)); BigValToBigInt (encBuffer, &TbsSig->s); CHK (DERAddIntegerFromArray (RootCert, encBuffer, encBufferLen)); CHK (DERPopNesting (RootCert)); CHK (DERPopNesting (RootCert)); CHK (DERPopNesting (RootCert)); ASRT (DERGetNestingDepth (RootCert) == 0); return 0; Error: return -1; }