diff --git a/.gitignore b/.gitignore index f1e3d20..d679182 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +# DICE test tools +*.pem + + # User-specific files *.suo *.user diff --git a/Emulator/AliasCert.der b/Emulator/AliasCert.der new file mode 100644 index 0000000..a4e4d90 Binary files /dev/null and b/Emulator/AliasCert.der differ diff --git a/Emulator/AliasCert.pem b/Emulator/AliasCert.pem new file mode 100644 index 0000000..adf0043 --- /dev/null +++ b/Emulator/AliasCert.pem @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIICUzCCAfqgAwIBAgIIPXSLudkxEoMwCgYIKoZIzj0EAwIwNDESMBAGA1UEAwwJUklvVCBDb3JlMQswCQYDVQQGDAJVUzERMA8GA1UECgwITVNSX1RFU1QwHhcNMTcwMTAxMDAwMDAwWhcNMzcwMTAxMDAwMDAwWjBDMSEwHwYDVQQDDBhMVjZ6OUEyY1dJR3VqSHNEMVBSdGlRPT0xCzAJBgNVBAYMAlVTMREwDwYDVQQKDAhNU1JfVEVTVDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGajjHdIVbV2PUPz3txkGqzH1DSVeZB7Uc/clZj4XJq7i8Sq6vTU3hANuHE7wyjAwHUme7z+2uALuwPq7lqLtB6jgeYwgeMwCwYDVR0PBAQDAgAEMBMGA1UdJQQMMAoGCCsGAQUFBwMCMCEGA1UdIwQaMBigFgQUJ5rnhPLv6uIGeN59l6X0PQ8MRrUwgZsGBmeBBQUEAQSBkDCBjQIBATBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOWa876ZQfrFhuVJnPLY6j6vNoT2NiwkYz93e+urv2bzaccYBfYoNNS+867QjYRvpLQQC6zPEp59dDM1kgj96x4wLQYJYIZIAWUDBAIBBCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAKBggqhkjOPQQDAgNHADBEAiBRXD1uueOWuQTT/sp/VP3NDMHpl783XcpRWtCmw7QDXwIgAhd1BzrOSgoGyq8C34oaXHIXItUJQwi0hCrv2SB0IGw= +-----END CERTIFICATE----- diff --git a/Emulator/AliasKey.der b/Emulator/AliasKey.der new file mode 100644 index 0000000..d958a30 Binary files /dev/null and b/Emulator/AliasKey.der differ diff --git a/Emulator/AliasKey.pem b/Emulator/AliasKey.pem new file mode 100644 index 0000000..37c0c10 --- /dev/null +++ b/Emulator/AliasKey.pem @@ -0,0 +1,3 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPI5+EGj2UWQQFmA7Ygzdj58XV47YqyB2TwBFVMIr+pfoAoGCCqGSM49AwEHoUQDQgAEZqOMd0hVtXY9Q/Pe3GQarMfUNJV5kHtRz9yVmPhcmruLxKrq9NTeEA24cTvDKMDAdSZ7vP7a4Au7A+ruWou0Hg== +-----END EC PRIVATE KEY----- diff --git a/Emulator/DeviceIDCrt.der b/Emulator/DeviceIDCrt.der new file mode 100644 index 0000000..74cccf4 Binary files /dev/null and b/Emulator/DeviceIDCrt.der differ diff --git a/Emulator/DeviceIDCrt.pem b/Emulator/DeviceIDCrt.pem new file mode 100644 index 0000000..d2da758 --- /dev/null +++ b/Emulator/DeviceIDCrt.pem @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBpDCCAUqgAwIBAgIIBRLow3RIMrAwCgYIKoZIzj0EAwIwNDESMBAGA1UEAwwJUklvVCBSMDB0MQswCQYDVQQGDAJVUzERMA8GA1UECgwITVNSX1RFU1QwHhcNMTcwMTAxMDAwMDAwWhcNMzcwMTAxMDAwMDAwWjA0MRIwEAYDVQQDDAlSSW9UIENvcmUxCzAJBgNVBAYMAlVTMREwDwYDVQQKDAhNU1JfVEVTVDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOWa876ZQfrFhuVJnPLY6j6vNoT2NiwkYz93e+urv2bzaccYBfYoNNS+867QjYRvpLQQC6zPEp59dDM1kgj96x6jRjBEMAsGA1UdDwQEAwIABDASBgNVHRMBAf8ECDAGAQH/AgEBMCEGA1UdIwQaMBigFgQUXevJbkUllKHIR0hqBYXzGKbUzVAwCgYIKoZIzj0EAwIDSAAwRQIgUVw9brnjlrkE0/7Kf1T9zQzB6Ze/N13KUVrQpsO0A18CIQCaROqEcN9XyESsY4DpSTIYoNmPSHAPU9RMqsmalWREOg== +-----END CERTIFICATE----- diff --git a/Emulator/DeviceIDPublic.der b/Emulator/DeviceIDPublic.der new file mode 100644 index 0000000..7ee7b89 Binary files /dev/null and b/Emulator/DeviceIDPublic.der differ diff --git a/Emulator/DeviceIDPublic.pem b/Emulator/DeviceIDPublic.pem new file mode 100644 index 0000000..9898c6c --- /dev/null +++ b/Emulator/DeviceIDPublic.pem @@ -0,0 +1,3 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5ZrzvplB+sWG5Umc8tjqPq82hPY2LCRjP3d766u/ZvNpxxgF9ig01L7zrtCNhG+ktBALrM8Snn10MzWSCP3rHg== +-----END PUBLIC KEY----- diff --git a/Emulator/R00tCrt.der b/Emulator/R00tCrt.der new file mode 100644 index 0000000..a29316f Binary files /dev/null and b/Emulator/R00tCrt.der differ diff --git a/Emulator/R00tCrt.pem b/Emulator/R00tCrt.pem new file mode 100644 index 0000000..529962c --- /dev/null +++ b/Emulator/R00tCrt.pem @@ -0,0 +1,3 @@ +-----BEGIN CERTIFICATE----- +MIIBgTCCASegAwIBAgIIGis8TV4AAAAwCgYIKoZIzj0EAwIwNDESMBAGA1UEAwwJUklvVCBSMDB0MQswCQYDVQQGDAJVUzERMA8GA1UECgwITVNSX1RFU1QwHhcNMTcwMTAxMDAwMDAwWhcNMzcwMTAxMDAwMDAwWjA0MRIwEAYDVQQDDAlSSW9UIFIwMHQxCzAJBgNVBAYMAlVTMREwDwYDVQQKDAhNU1JfVEVTVDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGmrWiahUg/J7F2llfSXSLn+0j0JxZ0fp1DTlEnI/Jzr3x5bsP2eRppj0jflBPvU+qJwT7EFnq2a1Tz4OWKxzn2jIzAhMAsGA1UdDwQEAwIABDASBgNVHRMBAf8ECDAGAQH/AgECMAoGCCqGSM49BAMCA0gAMEUCIFFcPW6545a5BNP+yn9U/c0MwemXvzddylFa0KbDtANfAiEA6T3h6/YLI4NcqiGjWIVCbAuUqQb3YS1lpJ63qVbBFsw= +-----END CERTIFICATE----- diff --git a/Emulator/RIoT/RIoTCrypt/RiotSha1.c b/Emulator/RIoT/RIoTCrypt/RiotSha1.c new file mode 100644 index 0000000..5a5b4c5 --- /dev/null +++ b/Emulator/RIoT/RIoTCrypt/RiotSha1.c @@ -0,0 +1,183 @@ +/* +* sha1.c +* +* Originally witten by Steve Reid +* +* Modified by Aaron D. Gifford +* +* NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN +* +* The original unmodified version is available at: +* ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +// +// 24-JAN-2018; RIoT adaptation (Paul England;MSFT). +// + + + +#include +#include "RiotSha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ + +#if (QCC_TARGET_ENDIAN == QCC_LITTLE_ENDIAN) +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&(sha1_quadbyte)0xFF00FF00) \ + |(rol(block->l[i],8)&(sha1_quadbyte)0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif + +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + +typedef union _BYTE64QUAD16 { + sha1_byte c[64]; + sha1_quadbyte l[16]; +} BYTE64QUAD16; + +/* Hash a single 512-bit block. This is the core of the algorithm. */ +void SHA1_Transform(sha1_quadbyte state[5], sha1_byte buffer[64]) { + sha1_quadbyte a, b, c, d, e; + BYTE64QUAD16 *block; + + block = (BYTE64QUAD16*)buffer; + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a, b, c, d, e, 0); R0(e, a, b, c, d, 1); R0(d, e, a, b, c, 2); R0(c, d, e, a, b, 3); + R0(b, c, d, e, a, 4); R0(a, b, c, d, e, 5); R0(e, a, b, c, d, 6); R0(d, e, a, b, c, 7); + R0(c, d, e, a, b, 8); R0(b, c, d, e, a, 9); R0(a, b, c, d, e, 10); R0(e, a, b, c, d, 11); + R0(d, e, a, b, c, 12); R0(c, d, e, a, b, 13); R0(b, c, d, e, a, 14); R0(a, b, c, d, e, 15); + R1(e, a, b, c, d, 16); R1(d, e, a, b, c, 17); R1(c, d, e, a, b, 18); R1(b, c, d, e, a, 19); + R2(a, b, c, d, e, 20); R2(e, a, b, c, d, 21); R2(d, e, a, b, c, 22); R2(c, d, e, a, b, 23); + R2(b, c, d, e, a, 24); R2(a, b, c, d, e, 25); R2(e, a, b, c, d, 26); R2(d, e, a, b, c, 27); + R2(c, d, e, a, b, 28); R2(b, c, d, e, a, 29); R2(a, b, c, d, e, 30); R2(e, a, b, c, d, 31); + R2(d, e, a, b, c, 32); R2(c, d, e, a, b, 33); R2(b, c, d, e, a, 34); R2(a, b, c, d, e, 35); + R2(e, a, b, c, d, 36); R2(d, e, a, b, c, 37); R2(c, d, e, a, b, 38); R2(b, c, d, e, a, 39); + R3(a, b, c, d, e, 40); R3(e, a, b, c, d, 41); R3(d, e, a, b, c, 42); R3(c, d, e, a, b, 43); + R3(b, c, d, e, a, 44); R3(a, b, c, d, e, 45); R3(e, a, b, c, d, 46); R3(d, e, a, b, c, 47); + R3(c, d, e, a, b, 48); R3(b, c, d, e, a, 49); R3(a, b, c, d, e, 50); R3(e, a, b, c, d, 51); + R3(d, e, a, b, c, 52); R3(c, d, e, a, b, 53); R3(b, c, d, e, a, 54); R3(a, b, c, d, e, 55); + R3(e, a, b, c, d, 56); R3(d, e, a, b, c, 57); R3(c, d, e, a, b, 58); R3(b, c, d, e, a, 59); + R4(a, b, c, d, e, 60); R4(e, a, b, c, d, 61); R4(d, e, a, b, c, 62); R4(c, d, e, a, b, 63); + R4(b, c, d, e, a, 64); R4(a, b, c, d, e, 65); R4(e, a, b, c, d, 66); R4(d, e, a, b, c, 67); + R4(c, d, e, a, b, 68); R4(b, c, d, e, a, 69); R4(a, b, c, d, e, 70); R4(e, a, b, c, d, 71); + R4(d, e, a, b, c, 72); R4(c, d, e, a, b, 73); R4(b, c, d, e, a, 74); R4(a, b, c, d, e, 75); + R4(e, a, b, c, d, 76); R4(d, e, a, b, c, 77); R4(c, d, e, a, b, 78); R4(b, c, d, e, a, 79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1_Init - Initialize new context */ +void SHA1_Init(SHA_CTX* context) { + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + +/* Run your data through this. */ +void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len) { + unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + /* Fill buffer, which may have data from a previous update. */ + memcpy(&context->buffer[j], data, (i = 64 - j)); + SHA1_Transform(context->state, context->buffer); + + /* Transform full blocks */ + j = 0; + for (; i + 63 < len; i += 64) { + memcpy(&context->buffer[j], &data[i], 64); + SHA1_Transform(context->state, context->buffer); + } + } + else i = 0; + + /* Not enough bytes to fill a block. Keep for next update */ + memcpy(&context->buffer[j], &data[i], len - i); +} + +void* SHA1_force_memset(void* s, int v, size_t n) { + volatile unsigned char* p = (volatile unsigned char*)s; + while (n--) *p++ = (unsigned char) v; + return s; +} + +/* Add padding and return the message digest. */ +void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX *context) { + sha1_quadbyte i, j; + sha1_byte finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (sha1_byte)((context->count[(i >= 4 ? 0 : 1)] + >> ((3 - (i & 3)) * 8)) & 255); /* Endian independent */ + } + SHA1_Update(context, (sha1_byte *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1_Update(context, (sha1_byte *)"\0", 1); + } + /* Should cause a SHA1_Transform() */ + SHA1_Update(context, finalcount, 8); + for (i = 0; i < SHA1_DIGEST_LENGTH; i++) { + digest[i] = (sha1_byte) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255); + } + /* Wipe variables */ + SHA1_force_memset(&i, 0, sizeof(i)); + SHA1_force_memset(&j, 0, sizeof(j)); + SHA1_force_memset(context->buffer, 0, SHA1_BLOCK_LENGTH); + SHA1_force_memset(context->state, 0, SHA1_DIGEST_LENGTH); + SHA1_force_memset(context->count, 0, 8); + SHA1_force_memset(&finalcount, 0, 8); +} + +void RIOT_SHA1_Block(const uint8_t *buf, size_t bufSize, uint8_t *digest) +{ + SHA_CTX context; + SHA1_Init(&context); + SHA1_Update(&context, (uint8_t*) buf, (unsigned int) bufSize); + SHA1_Final(digest, &context); +} + diff --git a/Emulator/RIoT/RIoTCrypt/RiotX509Bldr.c b/Emulator/RIoT/RIoTCrypt/RiotX509Bldr.c index 83c8063..58bd4ff 100644 --- a/Emulator/RIoT/RIoTCrypt/RiotX509Bldr.c +++ b/Emulator/RIoT/RIoTCrypt/RiotX509Bldr.c @@ -20,6 +20,7 @@ static int ecPublicKeyOID[] = { 1,2,840,10045, 2,1,-1 }; static int prime256v1OID[] = { 1,2,840,10045, 3,1,7,-1 }; static int keyUsageOID[] = { 2,5,29,15,-1 }; static int extKeyUsageOID[] = { 2,5,29,37,-1 }; +static int extAuthKeyIdentifierOID[] = { 2,5,29,35,-1 }; static int subjectAltNameOID[] = { 2,5,29,17,-1 }; static int clientAuthOID[] = { 1,3,6,1,5,5,7,3,2,-1 }; static int sha256OID[] = { 2,16,840,1,101,3,4,2,1,-1 }; @@ -28,6 +29,25 @@ static int countryNameOID[] = { 2,5,4,6,-1 }; static int orgNameOID[] = { 2,5,4,10,-1 }; static int basicConstraintsOID[] = { 2,5,29,19,-1 }; + +/* +Notes for Dennis. + Check RIotSha1.h/c these are new. I tried to make changes similar to what you did + for Sha256, but please scrub. + + +*/ + +static int GenerateGuidFromSeed(char* nameBuf, uint32_t *nameBufLen, const uint8_t* seed, size_t seedLen) +{ + uint8_t digest[RIOT_DIGEST_LENGTH]; + int result; + RIOT_SHA256_Block(seed, seedLen, digest); + result = Base64Encode(digest, 16, nameBuf, nameBufLen); + return result; +} + + static int X509AddExtensions( DERBuilderContext *Tbs, @@ -36,11 +56,27 @@ X509AddExtensions( uint8_t *Fwid, uint32_t FwidLen ) -// Create the RIoT extensions. The RIoT subject altName + extended key usage. +// Create the RIoT extensions. { - CHK(DERStartExplicit(Tbs, 3)); - CHK( DERStartSequenceOrSet(Tbs, true)); - CHK( DERStartSequenceOrSet(Tbs, true)); + uint8_t authKeyIdentifier[SHA1_DIGEST_LENGTH]; + RIOT_SHA1_Block(DevIdPub, DevIdPubLen, authKeyIdentifier); + uint8_t keyUsage = RIOT_X509_KEY_USAGE; + uint8_t extLen = 1; + + CHK(DERStartExplicit(Tbs, 3)); + + CHK( DERStartSequenceOrSet(Tbs, true)); + + // keyUsage + CHK( DERStartSequenceOrSet(Tbs, true)); + CHK( DERAddOID(Tbs, keyUsageOID)); + CHK( DERStartEnvelopingOctetString(Tbs)); + CHK( DERAddBitString(Tbs, &keyUsage, extLen)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + + // extendedKeyUsage + CHK( DERStartSequenceOrSet(Tbs, true)); CHK( DERAddOID(Tbs, extKeyUsageOID)); CHK( DERStartEnvelopingOctetString(Tbs)); CHK( DERStartSequenceOrSet(Tbs, true)); @@ -48,6 +84,20 @@ X509AddExtensions( CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); + + // authKeyIdentifier + CHK( DERStartSequenceOrSet(Tbs, true)); + CHK( DERAddOID(Tbs, extAuthKeyIdentifierOID)); + CHK( DERStartEnvelopingOctetString(Tbs)); + CHK( DERStartSequenceOrSet(Tbs, true)); + CHK( DERStartExplicit(Tbs, 0)); + CHK( DERAddOctetString(Tbs, authKeyIdentifier, 20)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + + // RIoT extension CHK( DERStartSequenceOrSet(Tbs, true)); CHK( DERAddOID(Tbs, riotOID)); CHK( DERStartEnvelopingOctetString(Tbs)); @@ -67,6 +117,7 @@ X509AddExtensions( CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); CHK(DERPopNesting(Tbs)); @@ -115,12 +166,21 @@ int X509GetDeviceCertTBS( DERBuilderContext *Tbs, RIOT_X509_TBS_DATA *TbsData, - RIOT_ECC_PUBLIC *DevIdKeyPub -) + RIOT_ECC_PUBLIC *DevIdKeyPub, + uint8_t *RootKeyPub, + uint32_t RootKeyPubLen) { - uint8_t encBuffer[65]; + uint8_t encBuffer[65]; uint32_t encBufferLen; uint8_t keyUsage = RIOT_X509_KEY_USAGE; + uint8_t authKeyIdentifier[SHA1_DIGEST_LENGTH]; + + RiotCrypt_ExportEccPub(DevIdKeyPub, encBuffer, &encBufferLen); + + if (RootKeyPub != NULL) + { + RIOT_SHA1_Block(RootKeyPub, RootKeyPubLen, authKeyIdentifier); + } CHK(DERStartSequenceOrSet(Tbs, true)); CHK( DERAddShortExplicitInteger(Tbs, 2)); @@ -139,19 +199,20 @@ X509GetDeviceCertTBS( CHK( DERAddOID(Tbs, ecPublicKeyOID)); CHK( DERAddOID(Tbs, prime256v1OID)); CHK( DERPopNesting(Tbs)); - RiotCrypt_ExportEccPub(DevIdKeyPub, encBuffer, &encBufferLen); CHK( DERAddBitString(Tbs, encBuffer, encBufferLen)); CHK( DERPopNesting(Tbs)); CHK( DERStartExplicit(Tbs, 3)); CHK( DERStartSequenceOrSet(Tbs, true)); - 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( DERStartSequenceOrSet(Tbs, true)); CHK( DERAddOID(Tbs, basicConstraintsOID)); CHK( DERAddBoolean(Tbs, true)); CHK( DERStartEnvelopingOctetString(Tbs)); @@ -161,7 +222,21 @@ X509GetDeviceCertTBS( CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); - CHK( DERPopNesting(Tbs)); + +if(RootKeyPub!=NULL) +{ + CHK( DERStartSequenceOrSet(Tbs, true)); + CHK( DERAddOID(Tbs, extAuthKeyIdentifierOID)); + CHK( DERStartEnvelopingOctetString(Tbs)); + CHK( DERStartSequenceOrSet(Tbs, true)); + CHK( DERStartExplicit(Tbs, 0)); + CHK( DERAddOctetString(Tbs, authKeyIdentifier, 20)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); + CHK( DERPopNesting(Tbs)); +} + CHK( DERPopNesting(Tbs)); CHK( DERPopNesting(Tbs)); CHK(DERPopNesting(Tbs)); @@ -215,9 +290,26 @@ X509GetAliasCertTBS( uint32_t FwidLen ) { - uint8_t encBuffer[65]; + int result; + char guidBuffer[64]; + uint8_t encBuffer[65]; uint32_t encBufferLen; + if (strcmp(TbsData->SubjectCommon, "*") == 0) + { + RiotCrypt_ExportEccPub(DevIdKeyPub, encBuffer, &encBufferLen); + uint32_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); + 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, RIOT_X509_SNUM_LEN)); @@ -493,4 +585,5 @@ X509MakeRootCert( Error: return -1; -} \ No newline at end of file +} + diff --git a/Emulator/RIoT/RIoTCrypt/include/RiotCrypt.h b/Emulator/RIoT/RIoTCrypt/include/RiotCrypt.h index 2c75833..f12990a 100644 --- a/Emulator/RIoT/RIoTCrypt/include/RiotCrypt.h +++ b/Emulator/RIoT/RIoTCrypt/include/RiotCrypt.h @@ -26,6 +26,7 @@ Confidential Information #include #include +#include "RiotSha1.h" #include "RiotSha256.h" #include "RiotAes128.h" #include "RiotHmac.h" diff --git a/Emulator/RIoT/RIoTCrypt/include/RiotSha1.h b/Emulator/RIoT/RIoTCrypt/include/RiotSha1.h new file mode 100644 index 0000000..b5fc43a --- /dev/null +++ b/Emulator/RIoT/RIoTCrypt/include/RiotSha1.h @@ -0,0 +1,100 @@ +#pragma once +/* +* sha.h +* +* Originally taken from the public domain SHA1 implementation +* written by by Steve Reid +* +* Modified by Aaron D. Gifford +* +* NO COPYRIGHT - THIS IS 100% IN THE PUBLIC DOMAIN +* +* The original unmodified version is available at: +* ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c +* +* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) AND CONTRIBUTORS ``AS IS'' AND +* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGE. +*/ + +// +// 24-JAN-2018; RIoT adaptation (Paul England;MSFT). +// + +#ifndef __RIOT_CRYPTO_SHA1_H__ +#define __RIOT_CRYPTO_SHA1_H__ + +#include "RiotTarget.h" + +typedef int asb; + +typedef uint8_t sha2_uint8_t; // Exactly 1 byte +typedef uint32_t sha2_word32; // Exactly 4 bytes +typedef uint64_t sha2_word64; // Exactly 8 bytes + +#define SHA1_DIGEST_LENGTH 20 + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Make sure you define these types for your architecture: */ + typedef unsigned int sha1_quadbyte; /* 4 byte type */ + typedef unsigned char sha1_byte; /* single byte type */ + + /* + * Be sure to get the above definitions right. For instance, on my + * x86 based FreeBSD box, I define LITTLE_ENDIAN and use the type + * "unsigned long" for the quadbyte. On FreeBSD on the Alpha, however, + * while I still use LITTLE_ENDIAN, I must define the quadbyte type + * as "unsigned int" instead. + */ + +#define SHA1_BLOCK_LENGTH 64 +#define SHA1_DIGEST_LENGTH 20 + + /* The SHA1 structure: */ + typedef struct _SHA_CTX { + sha1_quadbyte state[5]; + sha1_quadbyte count[2]; + sha1_byte buffer[SHA1_BLOCK_LENGTH]; + } SHA_CTX; + + void* SHA1_force_memset(void* s, int v, size_t n); + +#ifndef NOPROTO + void SHA1_Init(SHA_CTX *context); + void SHA1_Update(SHA_CTX *context, sha1_byte *data, unsigned int len); + void SHA1_Final(sha1_byte digest[SHA1_DIGEST_LENGTH], SHA_CTX* context); +#else + void SHA1_Init(); + void SHA1_Update(); + void SHA1_Final(); +#endif + + // + // Hash a block of data + // @param buf the buffer containing the data to hash + // @param bufSize the number of bytes in the buffer + // @param digest the buffer to hold the digest. Must be of size SHA1_DIGEST_LENGTH + // + void RIOT_SHA1_Block(const uint8_t *buf, size_t bufSize, + uint8_t *digest); + + + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Emulator/RIoT/RIoTCrypt/include/RiotX509Bldr.h b/Emulator/RIoT/RIoTCrypt/include/RiotX509Bldr.h index c57661f..7788799 100644 --- a/Emulator/RIoT/RIoTCrypt/include/RiotX509Bldr.h +++ b/Emulator/RIoT/RIoTCrypt/include/RiotX509Bldr.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define RIOT_X509_SNUM_LEN 0x05 +#define RIOT_X509_SNUM_LEN 0x08 // KeyUsage :: = BIT STRING{ // digitalSignature(0), @@ -38,7 +38,9 @@ int X509GetDeviceCertTBS( DERBuilderContext *Tbs, RIOT_X509_TBS_DATA *TbsData, - RIOT_ECC_PUBLIC *DevIdKeyPub + RIOT_ECC_PUBLIC *DevIdKeyPub, + uint8_t *RootKeyPub, + uint32_t RootKeyPubLen ); int diff --git a/Emulator/RIoTEmulator.cpp b/Emulator/RIoTEmulator.cpp index 090434a..79e19b9 100644 --- a/Emulator/RIoTEmulator.cpp +++ b/Emulator/RIoTEmulator.cpp @@ -41,11 +41,15 @@ uint8_t rDigest[DICE_DIGEST_LENGTH] = { // just pick a reasonable minimum buffer size and worry about this later. #define REASONABLE_MIN_CERT_SIZE DER_MAX_TBS -// The static data fields that make up the Alias Cert "to be signed" region +// The static data fields that make up the Alias Cert "to be signed" region. +// Note: if the device SubjectCommon is *, then a device-unique GUID is +// generated +// Note2: if a self-signed DeviceID cert is selected, then the tbs-data +// subject is also used for the issuer RIOT_X509_TBS_DATA x509AliasTBSData = { { 0x0A, 0x0B, 0x0C, 0x0D, 0x0E }, "RIoT Core", "MSR_TEST", "US", "170101000000Z", "370101000000Z", - "RIoT Device", "MSR_TEST", "US" }; + "*", "MSR_TEST", "US" }; // The static data fields that make up the DeviceID Cert "to be signed" region RIOT_X509_TBS_DATA x509DeviceTBSData = { { 0x0E, 0x0D, 0x0C, 0x0B, 0x0A }, @@ -59,11 +63,14 @@ RIOT_X509_TBS_DATA x509RootTBSData = { { 0x1A, 0x2B, 0x3C, 0x4D, 0x5E }, "170101000000Z", "370101000000Z", "RIoT R00t", "MSR_TEST", "US" }; -// Selectors for DeviceID cert handling (See comment below) +// Selectors for DeviceID cert handling. #define RIOT_ROOT_SIGNED 0x00 #define RIOT_SELF_SIGNED 0x01 #define RIOT_CSR 0x02 +#define DEVICE_ID_CERT_TYPE RIOT_ROOT_SIGNED + + // The "root" signing key. This is intended for development purposes only. // This key is used to sign the DeviceID certificate, the certificiate for // this "root" key represents the "trusted" CA for the developer-mode DPS @@ -83,6 +90,10 @@ BYTE eccRootPrivBytes[sizeof(ecc_privatekey)] = { 0x53, 0xf1, 0x56, 0x15, 0x02, 0xf0, 0x71, 0xc0, 0x53, 0x49, 0xc8, 0xda, 0xe6, 0x26, 0xa9, 0x0b, 0x17, 0x88, 0xe5, 0x70, 0x00, 0x00, 0x00, 0x00 }; +// Sets tbsData->SerialNumber to a quasi-random value derived from seedData +void SetSerialNumber(RIOT_X509_TBS_DATA* tbsData, const uint8_t* seedData, size_t seedLen); + + int CreateDeviceAuthBundle( BYTE *Seed, @@ -125,7 +136,7 @@ main() CreateDeviceAuthBundle(UDS, DICE_UDS_LENGTH, FWID, RIOT_DIGEST_LENGTH, deviceIDPub, &deviceIDPubSize, - devCert, &devCertSize, RIOT_ROOT_SIGNED, + devCert, &devCertSize, DEVICE_ID_CERT_TYPE, aliasKey, &aliaskeySize, aliasCert, &aliasCertSize); @@ -185,6 +196,9 @@ CreateDeviceAuthBundle( (const uint8_t *)RIOT_LABEL_IDENTITY, lblSize(RIOT_LABEL_IDENTITY)); + // Set the serial number + SetSerialNumber(&x509DeviceTBSData, digest, RIOT_DIGEST_LENGTH); + // Combine CDI and FWID, result in digest RiotCrypt_Hash2(digest, RIOT_DIGEST_LENGTH, digest, RIOT_DIGEST_LENGTH, @@ -197,6 +211,9 @@ CreateDeviceAuthBundle( (const uint8_t *)RIOT_LABEL_ALIAS, lblSize(RIOT_LABEL_ALIAS)); + // Set the serial number + SetSerialNumber(&x509AliasTBSData, digest, RIOT_DIGEST_LENGTH); + // Copy DeviceID Public length = sizeof(PEM); DERInitContext(&derCtx, derBuffer, DER_MAX_TBS); @@ -222,6 +239,7 @@ CreateDeviceAuthBundle( *AliasKeyEncodedSize = length; memcpy(AliasKeyEncoded, PEM, length); + #ifdef DEBUG printf("Alias Key"); PrintHex(derCtx.Buffer, derCtx.Position); @@ -243,12 +261,12 @@ CreateDeviceAuthBundle( // Generate Alias Key Certificate X509MakeAliasCert(&derCtx, &tbsSig); - // Copy Alias Key Certificate length = sizeof(PEM); DERtoPEM(&derCtx, CERT_TYPE, PEM, &length); *AliasCertBufSize = length; memcpy(AliasCertBuffer, PEM, length); + #ifdef DEBUG printf("Alias Cert"); PrintHex(derCtx.Buffer, derCtx.Position); @@ -267,8 +285,13 @@ CreateDeviceAuthBundle( if (DeviceCertType == RIOT_SELF_SIGNED) { // Generating self-signed DeviceID certificate + + x509DeviceTBSData.IssuerCommon = x509DeviceTBSData.SubjectCommon; + x509DeviceTBSData.IssuerOrg = x509DeviceTBSData.IssuerOrg; + x509DeviceTBSData.IssuerCountry = x509DeviceTBSData.SubjectCountry; + DERInitContext(&derCtx, derBuffer, DER_MAX_TBS); - X509GetDeviceCertTBS(&derCtx, &x509DeviceTBSData, &deviceIDPub); + X509GetDeviceCertTBS(&derCtx, &x509DeviceTBSData, &deviceIDPub, NULL, 0); // Sign the DeviceID Certificate's TBS region RiotCrypt_Sign(&tbsSig, derCtx.Buffer, derCtx.Position, &deviceIDPriv); @@ -289,8 +312,13 @@ CreateDeviceAuthBundle( } else { // Generating "root"-signed DeviceID certificate - DERInitContext(&derCtx, derBuffer, DER_MAX_TBS); - X509GetDeviceCertTBS(&derCtx, &x509DeviceTBSData, &deviceIDPub); + + uint8_t rootPubBuffer[65]; + uint32_t rootPubBufLen = 65; + RiotCrypt_ExportEccPub((RIOT_ECC_PUBLIC *)eccRootPubBytes, rootPubBuffer, &rootPubBufLen); + + DERInitContext(&derCtx, derBuffer, DER_MAX_TBS); + X509GetDeviceCertTBS(&derCtx, &x509DeviceTBSData, &deviceIDPub, rootPubBuffer, rootPubBufLen); // Sign the DeviceID Certificate's TBS region RiotCrypt_Sign(&tbsSig, derCtx.Buffer, derCtx.Position, (RIOT_ECC_PRIVATE *)eccRootPrivBytes); @@ -301,9 +329,16 @@ CreateDeviceAuthBundle( X509MakeDeviceCert(&derCtx, &tbsSig); } - // Copy DeviceID Certificate or CSR + // Copy DeviceID Certificate or CSR Note: depending on DeviceCertType this + // may be self-signed, Root-signed, or a CSR + uint32_t pemType = CERT_TYPE; + if (DeviceCertType == RIOT_CSR) + { + pemType = CERT_REQ_TYPE; + } + length = sizeof(PEM); - DERtoPEM(&derCtx, CERT_TYPE, PEM, &length); + DERtoPEM(&derCtx, pemType, PEM, &length); *DeviceCertBufSize = length; memcpy(DeviceCertBuffer, PEM, length); @@ -321,7 +356,7 @@ CreateDeviceAuthBundle( X509GetRootCertTBS(&derCtx, &x509RootTBSData, (RIOT_ECC_PUBLIC*)eccRootPubBytes); // Self-sign the "root" Certificate's TBS region - RiotCrypt_Sign(&tbsSig, derCtx.Buffer, derCtx.Position, &deviceIDPriv); + RiotCrypt_Sign(&tbsSig, derCtx.Buffer, derCtx.Position, (RIOT_ECC_PRIVATE *)eccRootPrivBytes); // Generate "root" CA cert X509MakeRootCert(&derCtx, &tbsSig); @@ -342,6 +377,24 @@ CreateDeviceAuthBundle( return 0; } +void SetSerialNumber(RIOT_X509_TBS_DATA* tbsData, const uint8_t* seedData, size_t seedLen) +{ + // Set the tbsData serial number to 8 bytes of data derived from seedData + uint8_t hashBuf[DICE_DIGEST_LENGTH]; + // SHA-1 hash of "DICE SEED" == 6e785006 84941d8f 7880520c 60b8c7e4 3f1a3c00 + uint8_t seedExtender[20] = { 0x6e, 0x78, 0x50, 0x06, 0x84, 0x94, 0x1d, 0x8f, 0x78, + 0x80, 0x52, 0x0c, 0x60, 0xb8, 0xc7, 0xe4, 0x3f, 0x1a, 0x3c, 0x00 }; + + DiceSHA256_2(seedData, seedLen, seedExtender, sizeof(seedExtender), hashBuf); + // Take first 8 bytes to form serial number + memcpy(tbsData->SerialNum, hashBuf, RIOT_X509_SNUM_LEN); + // DER encoded serial number must be positive and the first byte must not be zero + tbsData->SerialNum[0] &= (uint8_t)0x7f; + tbsData->SerialNum[0] |= (uint8_t)0x01; + return; +} + + #ifdef DEBUG void HexConvert(uint8_t* in, int inLen, char* outBuf, int outLen) { diff --git a/Emulator/RIoTEmulator.vcxproj b/Emulator/RIoTEmulator.vcxproj index 116ee0e..53dfa54 100644 --- a/Emulator/RIoTEmulator.vcxproj +++ b/Emulator/RIoTEmulator.vcxproj @@ -166,6 +166,7 @@ + @@ -184,6 +185,7 @@ + diff --git a/Emulator/RIoTEmulator.vcxproj.filters b/Emulator/RIoTEmulator.vcxproj.filters index d5004a6..45fcfa1 100644 --- a/Emulator/RIoTEmulator.vcxproj.filters +++ b/Emulator/RIoTEmulator.vcxproj.filters @@ -36,6 +36,9 @@ RIoT\RIoTCrypt + + RIoT\RIoTCrypt + @@ -79,6 +82,9 @@ RIoT\RIoTCrypt\Headers + + RIoT\RIoTCrypt\Headers + diff --git a/README.md b/README.md index e62fc34..a2ef381 100644 --- a/README.md +++ b/README.md @@ -22,5 +22,3 @@ Soon we will also share demos and sample code for specific DICE-enabled hardware For more information on DICE, and to learn how you can contribute, we encourage you to check out the [DICE Architectures workgroup](https://trustedcomputinggroup.org/work-groups/dice-architectures/) (DiceArch) in the [Trusted Computing Group](https://trustedcomputinggroup.org/). For questions, comments, or contributions to the RIoT project from MSR, feel free to contact us at riotdev@microsoft.com. - - diff --git a/Reference/DICE/DICE.vcxproj b/Reference/DICE/DICE.vcxproj index b792bfe..7dc84f0 100644 --- a/Reference/DICE/DICE.vcxproj +++ b/Reference/DICE/DICE.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -22,32 +22,32 @@ {0E4A2BB0-FBC0-4F2D-80A7-A10359BF6B07} Win32Proj DICE - 8.1 + 10.0.16299.0 Application true - v140 + v141 Unicode Application false - v140 + v141 true Unicode Application true - v140 + v141 Unicode Application false - v140 + v141 true Unicode diff --git a/Reference/FW/Loader.vcxproj b/Reference/FW/Loader.vcxproj index aef9b93..f88bb0c 100644 --- a/Reference/FW/Loader.vcxproj +++ b/Reference/FW/Loader.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -15,18 +15,19 @@ Win32Proj Loader FW + 10.0.16299.0 DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode diff --git a/Reference/RIoT/Core/RIoT.vcxproj b/Reference/RIoT/Core/RIoT.vcxproj index 51b85a5..cf9a606 100644 --- a/Reference/RIoT/Core/RIoT.vcxproj +++ b/Reference/RIoT/Core/RIoT.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -14,18 +14,19 @@ {B7AF6C41-115E-4926-A8B3-7842FFE9D605} Win32Proj RIoT + 10.0.16299.0 DynamicLibrary true - v140 + v141 Unicode DynamicLibrary false - v140 + v141 true Unicode diff --git a/Tools/DICETest/CertChecker.cs b/Tools/DICETest/CertChecker.cs index 88bb86b..ac75789 100644 --- a/Tools/DICETest/CertChecker.cs +++ b/Tools/DICETest/CertChecker.cs @@ -5,10 +5,12 @@ namespace DICETest { using System; + using System.Linq; using System.IO; using Org.BouncyCastle.Asn1; using Org.BouncyCastle.Asn1.Nist; using Org.BouncyCastle.Asn1.X509; + using Org.BouncyCastle.Math; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.X509; using Org.BouncyCastle.X509.Extension; @@ -199,6 +201,7 @@ namespace DICETest internal bool CheckSubjectIssuerLinkage() { bool ok = true; + Notify($"Checking Subject/Issuer Linkage"); foreach (var c in Certs) { Notify($" {c.SubjectDN.ToString()}"); @@ -217,6 +220,10 @@ namespace DICETest ok = false; } } + if(ok) + { + NotifySuccess("OK"); + } return ok; } @@ -226,6 +233,8 @@ namespace DICETest /// Chain signing linkage is OK internal bool CheckSigningLinkage() { + Notify($"Checking signature chains"); + bool ok = true; // alias to cert-before-root should be signed by parent for (int j = 0; j < NumCerts - 1; j++) @@ -239,7 +248,7 @@ namespace DICETest } catch(Exception e) { - Error($"Cert {target.SubjectDN.ToString()} is not properly signed by {signer.SubjectDN.ToString()}. Error is {e.ToString()}"); + Error($" Cert {target.SubjectDN.ToString()} is not properly signed by {signer.SubjectDN.ToString()}. Error is {e.ToString()}"); ok = false; } } @@ -250,11 +259,15 @@ namespace DICETest { root.Verify(rootPubKey); } - catch (Exception e) + catch (Exception) { - Error($"Root cert is not properly self-signed. Error is {e.ToString()}"); + Error($"Root cert is not properly self-signed."); ok = false; } + if(ok) + { + NotifySuccess("OK"); + } return ok; } @@ -447,7 +460,12 @@ namespace DICETest try { var keyUsage= c.GetKeyUsage(); - if(keyUsage.Length>9) + if(keyUsage==null) + { + Error($"KeyUsage is missing."); + return false; + } + if (keyUsage.Length>9) { Error($"Unsupported KeyUsage. This usually means that DecipherOnly is asserted, which is an error"); return false; @@ -550,13 +568,21 @@ namespace DICETest /// bool CheckSerialNumber(X509Certificate c) { - var sn = c.SerialNumber; - int snNumBytes = sn.ToByteArray().Length; + BigInteger sn = c.SerialNumber; + var snBytes = sn.ToByteArray(); + int snNumBytes = snBytes.Length; if(snNumBytes x == 0); + if (numZeroBytes>=3) + { + Warning($"Serial number has {numZeroBytes} zeros. Is it random?"); + return false; + } + return true; } diff --git a/Tools/DICETest/Program.cs b/Tools/DICETest/Program.cs index 97bcb4a..1d633b6 100644 --- a/Tools/DICETest/Program.cs +++ b/Tools/DICETest/Program.cs @@ -18,6 +18,12 @@ namespace DICETest { // Usage: // -option c0 c1 c2... + + // Examples: + // -chain AliasCert.PEM DeviceIDCrt.PEM R00tCrt.PEM + // -chain AliasCert.PEM DeviceIDCrt.PEM + // -csr DeviceIDCrt.PEM + if (args.Length == 0 || args[1] == "?") { PrintHelp(); @@ -43,6 +49,7 @@ namespace DICETest { Program.Print("One or more errors in certificate chain.", NotifyType.Error); } + else { Program.Print("Certificates and certificate chain are valid.", NotifyType.Success); } diff --git a/Tools/RIoT/Main.cs b/Tools/RIoT/Main.cs index 6dc6636..505b273 100644 --- a/Tools/RIoT/Main.cs +++ b/Tools/RIoT/Main.cs @@ -67,6 +67,8 @@ namespace RIoT bool ok = ParseParms(args); if (!ok) return; + string workingDir = Environment.CurrentDirectory; + foreach(var action in ActiveParms) { if (action.Flag == "dir")