// create a new open packet packet_t crypt_openize_1a(crypt_t self, crypt_t c, packet_t inner) { unsigned char secret[uECC_BYTES], iv[16], hash[32]; packet_t open; int inner_len; crypt_1a_t cs = (crypt_1a_t)c->cs, scs = (crypt_1a_t)self->cs; open = packet_chain(inner); packet_json(open,&(self->csid),1); inner_len = packet_len(inner); if(!packet_body(open,NULL,4+40+inner_len)) return NULL; // copy in the line public key memcpy(open->body+4, cs->line_public, 40); // get the shared secret to create the iv+key for the open aes if(!uECC_shared_secret(cs->id_public, cs->line_private, secret)) return packet_free(open); crypt_hash(secret,uECC_BYTES,hash); fold1(hash,hash); memset(iv,0,16); iv[15] = 1; // encrypt the inner aes_128_ctr(hash,inner_len,iv,packet_raw(inner),open->body+4+40); // generate secret for hmac if(!uECC_shared_secret(cs->id_public, scs->id_private, secret)) return packet_free(open); hmac_256(secret,uECC_BYTES,open->body+4,40+inner_len,hash); fold3(hash,open->body); return open; }
lob_t remote_encrypt(remote_t remote, local_t local, lob_t inner) { uint8_t shared[uECC_BYTES+4], iv[16], hash[32], csid = 0x1a; lob_t outer; size_t inner_len; outer = lob_new(); lob_head(outer,&csid,1); inner_len = lob_len(inner); if(!lob_body(outer,NULL,21+4+inner_len+4)) return lob_free(outer); // copy in the ephemeral public key memcpy(outer->body, remote->ecomp, uECC_BYTES+1); // get the shared secret to create the iv+key for the open aes if(!uECC_shared_secret(remote->key, remote->esecret, shared)) return lob_free(outer); e3x_hash(shared,uECC_BYTES,hash); fold1(hash,hash); memset(iv,0,16); memcpy(iv,&(remote->seq),4); remote->seq++; // increment seq after every use memcpy(outer->body+21,iv,4); // send along the used IV // encrypt the inner into the outer aes_128_ctr(hash,inner_len,iv,lob_raw(inner),outer->body+21+4); // generate secret for hmac if(!uECC_shared_secret(remote->key, local->secret, shared)) return lob_free(outer); memcpy(shared+uECC_BYTES,outer->body+21,4); // use the IV too hmac_256(shared,uECC_BYTES+4,outer->body,21+4+inner_len,hash); fold3(hash,outer->body+21+4+inner_len); // write into last 4 bytes return outer; }
// makes sure all the crypto line state is set up, and creates line keys if exist int crypt_line_1a(crypt_t c, packet_t inner) { unsigned char line_public[uECC_BYTES*2], secret[uECC_BYTES], input[uECC_BYTES+16+16], hash[32]; char *hecc; crypt_1a_t cs; cs = (crypt_1a_t)c->cs; hecc = packet_get_str(inner,"ecc"); // it's where we stashed it if(!hecc || strlen(hecc) != uECC_BYTES*4) return 1; crypt_rand((unsigned char*)&(cs->seq),4); // init seq to random start // do the diffie hellman util_unhex((unsigned char*)hecc,uECC_BYTES*4,line_public); if(!uECC_shared_secret(line_public, cs->line_private, secret)) return 1; // make line keys! memcpy(input,secret,uECC_BYTES); memcpy(input+uECC_BYTES,c->lineOut,16); memcpy(input+uECC_BYTES+16,c->lineIn,16); crypt_hash(input,uECC_BYTES+16+16,hash); fold1(hash,cs->keyOut); memcpy(input+uECC_BYTES,c->lineIn,16); memcpy(input+uECC_BYTES+16,c->lineOut,16); crypt_hash(input,uECC_BYTES+16+16,hash); fold1(hash,cs->keyIn); return 0; }
lob_t local_decrypt(local_t local, lob_t outer) { uint8_t key[uECC_BYTES*2], shared[uECC_BYTES], iv[16], hash[32]; lob_t inner, tmp; // * `KEY` - 21 bytes, the sender's ephemeral exchange public key in compressed format // * `IV` - 4 bytes, a random but unique value determined by the sender // * `INNER` - (minimum 21+2 bytes) the AES-128-CTR encrypted inner packet ciphertext // * `HMAC` - 4 bytes, the calculated HMAC of all of the previous KEY+INNER bytes if(outer->body_len <= (21+4+0+4)) return NULL; tmp = lob_new(); if(!lob_body(tmp,NULL,outer->body_len-(4+21+4))) return lob_free(tmp); // get the shared secret to create the iv+key for the open aes uECC_decompress(outer->body,key); if(!uECC_shared_secret(key, local->secret, shared)) return lob_free(tmp); e3x_hash(shared,uECC_BYTES,hash); fold1(hash,hash); memset(iv,0,16); memcpy(iv,outer->body+21,4); // decrypt the inner aes_128_ctr(hash,tmp->body_len,iv,outer->body+4+21,tmp->body); // load inner packet inner = lob_parse(tmp->body,tmp->body_len); lob_free(tmp); return inner; }
ephemeral_t ephemeral_new(remote_t remote, lob_t outer) { uint8_t ekey[uECC_BYTES*2], shared[uECC_BYTES+((uECC_BYTES+1)*2)], hash[32]; ephemeral_t ephem; if(!remote) return NULL; if(!outer || outer->body_len < (uECC_BYTES+1)) return LOG("invalid outer"); if(!(ephem = malloc(sizeof(struct ephemeral_struct)))) return NULL; memset(ephem,0,sizeof (struct ephemeral_struct)); // create and copy in the exchange routing token e3x_hash(outer->body,16,hash); memcpy(ephem->token,hash,16); // generate a random seq starting point for channel IV's e3x_rand((uint8_t*)&(ephem->seq),4); // decompress the exchange key and get the shared secret uECC_decompress(outer->body,ekey); if(!uECC_shared_secret(ekey, remote->esecret, shared)) return LOG("ECDH failed"); // combine inputs to create the digest memcpy(shared+uECC_BYTES,remote->ecomp,uECC_BYTES+1); memcpy(shared+uECC_BYTES+uECC_BYTES+1,outer->body,uECC_BYTES+1); e3x_hash(shared,uECC_BYTES+((uECC_BYTES+1)*2),hash); fold1(hash,ephem->enckey); memcpy(shared+uECC_BYTES,outer->body,uECC_BYTES+1); memcpy(shared+uECC_BYTES+uECC_BYTES+1,remote->ecomp,uECC_BYTES+1); e3x_hash(shared,uECC_BYTES+((uECC_BYTES+1)*2),hash); fold1(hash,ephem->deckey); return ephem; }
int main(void) { uint32_t err_code; uint32_t time0, time1; LOG("Starting LFCLK"); err_code = nrf_drv_clock_init(); APP_ERROR_CHECK(err_code); nrf_drv_clock_lfclk_request(NULL); LOG("Starting RTC"); err_code = nrf_drv_rtc_init(&rtc, NULL, &rtc_handler); APP_ERROR_CHECK(err_code); nrf_drv_rtc_tick_enable(&rtc, false); nrf_drv_rtc_enable(&rtc); LOG("Starting RNG"); err_code = nrf_drv_rng_init(NULL); APP_ERROR_CHECK(err_code); while (1) { /* get a random key */ time0 = nrf_drv_rtc_counter_get(&rtc); uECC_make_key(public_key, private_key); time1 = nrf_drv_rtc_counter_get(&rtc); LOG("Key time was %u ", time1 - time0); /* use the key to sign the hash */ time0 = nrf_drv_rtc_counter_get(&rtc); uECC_sign(private_key, hash, signature); time1 = nrf_drv_rtc_counter_get(&rtc); LOG("Sig Time was %u ", time1 - time0); /* verify the signature */ time0 = nrf_drv_rtc_counter_get(&rtc); uECC_verify(public_key, hash, signature); time1 = nrf_drv_rtc_counter_get(&rtc); LOG("Verify Time was %u ", time1 - time0); time0 = nrf_drv_rtc_counter_get(&rtc); uECC_shared_secret(public_key, private_key, secret); time1 = nrf_drv_rtc_counter_get(&rtc); LOG("SS Time was %u ", time1 - time0); time0 = nrf_drv_rtc_counter_get(&rtc); sha256_init(&context); sha256_update(&context, message, 20); sha256_final(&context, shahash); time1 = nrf_drv_rtc_counter_get(&rtc); LOG("SHA Time was %u ", time1 - time0); } return 0; }
int joylink_encrypt_sub_dev_data( uint8_t* pBuf, int buflen, E_EncType enctype, uint8_t* key, const uint8_t* payload, int length) { char* psJson = (char*)payload; uint8_t* pOut = pBuf; int retlen; uint8_t peerPubKey[uECC_BYTES * 2] = {0}; uint8_t secret[uECC_BYTES] = {0}; switch (enctype) { case ET_NOTHING: break; case ET_PSKAES: break; case ET_ACCESSKEYAES: retlen = device_aes_encrypt( key, 16, key+16, (uint8_t*)psJson, length, pOut, length + 16); break; case ET_ECDH: memcpy(pOut, __g_ekey.devPubKeyC, uECC_BYTES + 1); pOut += (uECC_BYTES + 1); uECC_decompress(key, peerPubKey); uECC_shared_secret( peerPubKey, __g_ekey.priKey, secret); retlen = device_aes_encrypt( secret, 16, key + 4, (const uint8_t*)psJson, length, pOut, length + 16); break; default: break; } return retlen; }
packet_t crypt_deopenize_1a(crypt_t self, packet_t open) { unsigned char secret[uECC_BYTES], iv[16], b64[uECC_BYTES*2*2], hash[32]; packet_t inner, tmp; crypt_1a_t cs = (crypt_1a_t)self->cs; if(open->body_len <= (4+40)) return NULL; inner = packet_new(); if(!packet_body(inner,NULL,open->body_len-(4+40))) return packet_free(inner); // get the shared secret to create the iv+key for the open aes if(!uECC_shared_secret(open->body+4, cs->id_private, secret)) return packet_free(inner); crypt_hash(secret,uECC_BYTES,hash); fold1(hash,hash); memset(iv,0,16); iv[15] = 1; // decrypt the inner aes_128_ctr(hash,inner->body_len,iv,open->body+4+40,inner->body); // load inner packet if((tmp = packet_parse(inner->body,inner->body_len)) == NULL) return packet_free(inner); packet_free(inner); inner = tmp; // generate secret for hmac if(inner->body_len != uECC_BYTES*2) return packet_free(inner); if(!uECC_shared_secret(inner->body, cs->id_private, secret)) return packet_free(inner); // verify hmac_256(secret,uECC_BYTES,open->body+4,open->body_len-4,hash); fold3(hash,hash); if(memcmp(hash,open->body,4) != 0) return packet_free(inner); // stash the hex line key w/ the inner util_hex(open->body+4,40,b64); packet_set_str(inner,"ecc",(char*)b64); return inner; }
int yacl_ecdh (const uint8_t public_key[YACL_P256_COORD_SIZE*2], const uint8_t private_key[YACL_P256_COORD_SIZE], uint8_t secret[YACL_P256_COORD_SIZE]) { int rc; rc = uECC_shared_secret(public_key, private_key, secret); if (1 == rc) rc = 0; else rc = 1; return rc; }
uint8_t remote_verify(remote_t remote, local_t local, lob_t outer) { uint8_t shared[uECC_BYTES+4], hash[32]; if(!remote || !local || !outer) return 1; if(outer->head_len != 1 || outer->head[0] != 0x1a) return 2; // generate the key for the hmac, combining the shared secret and IV if(!uECC_shared_secret(remote->key, local->secret, shared)) return 3; memcpy(shared+uECC_BYTES,outer->body+21,4); // verify hmac_256(shared,uECC_BYTES+4,outer->body,outer->body_len-4,hash); fold3(hash,hash); if(util_ct_memcmp(hash,outer->body+(outer->body_len-4),4) != 0) { LOG("hmac failed"); return 4; } return 0; }
int main(void) { printf("micro-ecc compiled!\n"); const struct uECC_Curve_t *curve = uECC_secp256r1(); int i, errorc = 0; int curve_size = uECC_curve_private_key_size(curve); int public_key_size = uECC_curve_public_key_size(curve); uint8_t l_secret1[curve_size]; uint8_t l_secret2[curve_size]; /* reserve space for a SHA-256 hash */ uint8_t l_hash[32] = { 0 }; uint8_t l_sig[public_key_size]; printf("Testing %d random private key pairs and signature without using HWRNG\n", TESTROUNDS); /* use pre-generated keys for no-HWRNG platforms */ uint8_t l_private1[] = { 0x9b, 0x4c, 0x4b, 0xa0, 0xb7, 0xb1, 0x25, 0x23, 0x9c, 0x09, 0x85, 0x4f, 0x9a, 0x21, 0xb4, 0x14, 0x70, 0xe0, 0xce, 0x21, 0x25, 0x00, 0xa5, 0x62, 0x34, 0xa4, 0x25, 0xf0, 0x0f, 0x00, 0xeb, 0xe7, }; uint8_t l_public1[] = { 0x54, 0x3e, 0x98, 0xf8, 0x14, 0x55, 0x08, 0x13, 0xb5, 0x1a, 0x1d, 0x02, 0x02, 0xd7, 0x0e, 0xab, 0xa0, 0x98, 0x74, 0x61, 0x91, 0x12, 0x3d, 0x96, 0x50, 0xfa, 0xd5, 0x94, 0xa2, 0x86, 0xa8, 0xb0, 0xd0, 0x7b, 0xda, 0x36, 0xba, 0x8e, 0xd3, 0x9a, 0xa0, 0x16, 0x11, 0x0e, 0x1b, 0x6e, 0x81, 0x13, 0xd7, 0xf4, 0x23, 0xa1, 0xb2, 0x9b, 0xaf, 0xf6, 0x6b, 0xc4, 0x2a, 0xdf, 0xbd, 0xe4, 0x61, 0x5c, }; uint8_t l_private2[] = { 0xb5, 0x45, 0xaf, 0xa0, 0x2e, 0x5c, 0xa6, 0x17, 0x3b, 0x5a, 0x55, 0x76, 0x67, 0x5d, 0xd4, 0x5e, 0x41, 0x7c, 0x4f, 0x19, 0x9f, 0xb9, 0x75, 0xdc, 0xba, 0x57, 0xc4, 0xa2, 0x26, 0xc6, 0x86, 0x2a, }; uint8_t l_public2[] = { 0x2e, 0x81, 0x24, 0x3c, 0x44, 0xac, 0x63, 0x13, 0x9b, 0xc1, 0x27, 0xe9, 0x53, 0x3b, 0x0a, 0xe2, 0xf9, 0x22, 0xcd, 0x06, 0xfd, 0x12, 0x17, 0x2e, 0xe5, 0x0e, 0xb5, 0xce, 0x6b, 0x50, 0xe2, 0x44, 0xbf, 0x6b, 0x3f, 0xe8, 0x4e, 0x70, 0xd1, 0x06, 0x85, 0x84, 0xb8, 0xef, 0xe2, 0x25, 0x91, 0x21, 0xf3, 0x46, 0x70, 0xa9, 0x1c, 0x79, 0x19, 0xe3, 0xfb, 0x11, 0x36, 0x64, 0x37, 0x64, 0x58, 0xc9, }; uint8_t tmp[2 * SHA256_DIGEST_LENGTH + SHA256_INTERNAL_BLOCK_SIZE]; for (i = 0; i < TESTROUNDS; ++i) { printf("."); if (!uECC_shared_secret(l_public2, l_private1, l_secret1, curve)) { printf("\nRound %d: shared_secret() failed (1)", i); errorc++; } else { if (!uECC_shared_secret(l_public1, l_private2, l_secret2, curve)) { printf("\nRound: %d: shared_secret() failed (2)", i); errorc++; } else { if (memcmp(l_secret1, l_secret2, sizeof(l_secret1)) != 0) { printf("\nShared secrets are not identical!\n"); errorc++; } /* copy some bogus data into the hash */ memcpy(l_hash, l_public1, 32); uECC_SHA256_HashContext ctx; ctx.uECC.init_hash = &_init_sha256; ctx.uECC.update_hash = &_update_sha256; ctx.uECC.finish_hash = &_finish_sha256; ctx.uECC.block_size = 64; ctx.uECC.result_size = 32; ctx.uECC.tmp = tmp; if (uECC_sign_deterministic(l_private1, l_hash, sizeof(l_hash), &ctx.uECC, l_sig, curve) != 1) { printf("\nRound %d: uECC_sign_deterministic() failed", i); errorc++; } else { if (uECC_verify(l_public1, l_hash, sizeof(l_hash), l_sig, curve) != 1) { printf("\nRound %d: uECC_verify() failed", i); errorc++; } } } } } printf(" done with %d error(s)\n", errorc); if (errorc == 0) { return 0; } else { return 1; } }
int main(void) { printf("micro-ecc compiled!\n"); const struct uECC_Curve_t *curve = uECC_secp256r1(); int i, errorc = 0; int curve_size = uECC_curve_private_key_size(curve); int public_key_size = uECC_curve_public_key_size(curve); uint8_t l_secret1[curve_size]; uint8_t l_secret2[curve_size]; /* reserve space for a SHA-256 hash */ uint8_t l_hash[32] = { 0 }; uint8_t l_sig[public_key_size]; printf("Testing %d random private key pairs and signature using HWRNG\n", TESTROUNDS); uint8_t l_private1[curve_size]; uint8_t l_private2[curve_size]; uint8_t l_public1[public_key_size]; uint8_t l_public2[public_key_size]; for (i = 0; i < TESTROUNDS; ++i) { printf("."); if (!uECC_make_key(l_public1, l_private1, curve) || !uECC_make_key(l_public2, l_private2, curve)) { printf("\nRound %d: uECC_make_key() failed", i); errorc++; } else { if (!uECC_shared_secret(l_public2, l_private1, l_secret1, curve)) { printf("\nRound %d: shared_secret() failed (1)", i); errorc++; } else { if (!uECC_shared_secret(l_public1, l_private2, l_secret2, curve)) { printf("\nRound: %d: shared_secret() failed (2)", i); errorc++; } else { if (memcmp(l_secret1, l_secret2, sizeof(l_secret1)) != 0) { printf("\nShared secrets are not identical!\n"); errorc++; } /* copy some bogus data into the hash */ memcpy(l_hash, l_public1, 32); if ((uECC_sign(l_private1, l_hash, sizeof(l_hash), l_sig, curve)) != 1) { printf("\nRound %d: uECC_sign() failed", i); errorc++; } else { if ((uECC_verify(l_public1, l_hash, sizeof(l_hash), l_sig, curve)) != 1) { printf("\nRound %d: uECC_verify() failed", i); errorc++; } } } } } } printf(" done with %d error(s)\n", errorc); if (errorc) { puts("FAILURE"); return 1; } else { puts("SUCCESS"); return 0; } }
int main(void) { printf("micro-ecc compiled!\n"); int i, errorc = 0; uint8_t l_private1[uECC_BYTES]; uint8_t l_private2[uECC_BYTES]; uint8_t l_public1[uECC_BYTES * 2]; uint8_t l_public2[uECC_BYTES * 2]; uint8_t l_secret1[uECC_BYTES]; uint8_t l_secret2[uECC_BYTES]; uint8_t l_hash[uECC_BYTES]; uint8_t l_sig[uECC_BYTES * 2]; /* initialize hardware random number generator */ random_init(); /* power off RNG to save energy */ random_poweroff(); printf("Testing %d random private key pairs and signature\n", TESTROUNDS); for (i = 0; i < TESTROUNDS; ++i) { printf("."); if (!uECC_make_key(l_public1, l_private1) || !uECC_make_key(l_public2, l_private2)) { printf("\nRound %d: uECC_make_key() failed", i); errorc++; } else { if (!uECC_shared_secret(l_public2, l_private1, l_secret1)) { printf("\nRound %d: shared_secret() failed (1)", i); errorc++; } else { if (!uECC_shared_secret(l_public1, l_private2, l_secret2)) { printf("\nRound: %d: shared_secret() failed (2)", i); errorc++; } else { if (memcmp(l_secret1, l_secret2, sizeof(l_secret1)) != 0) { printf("\nShared secrets are not identical!\n"); errorc++; } memcpy(l_hash, l_public1, uECC_BYTES); if ((uECC_sign(l_private1, l_hash, l_sig)) != 1) { printf("\nRound %d: uECC_sign() failed", i); errorc++; } else { if ((uECC_verify(l_public1, l_hash, l_sig)) != 1) { printf("\nRound %d: uECC_verify() failed", i); errorc++; } } } } } } printf(" done with %d error(s)\n", errorc); if (errorc == 0) { return 0; } else { return 1; } }