int main() { uint8_t a_pub[ECC_BYTES+1]; uint8_t a_pri[ECC_BYTES]; uint8_t b_pub[ECC_BYTES+1]; uint8_t b_pri[ECC_BYTES]; uint8_t a_secret[ECC_BYTES]; uint8_t b_secret[ECC_BYTES]; uint8_t p_signature[ECC_BYTES*2]; uint8_t a_hash[SHA256_BLOCK_SIZE]; uint8_t b_hash[SHA256_BLOCK_SIZE]; SHA256_CTX ctx; int errid = 0; int i=0; /* print ECC_CURVE parameter */ print_parameter(ECC_CURVE); /* make key */ errid = ecc_make_key(a_pub,a_pri); if(errid != 1){ printf("[ecc_make _key] error!!!"); return -1; } printf("A key pair generation completed...\n"); errid = ecc_make_key(b_pub,b_pri); if(errid != 1){ printf("[ecc_make _key] error!!!"); return -1; } printf("B key pair generation completed...\n"); /* compute shared secret */ errid = ecdh_shared_secret(b_pub,a_pri,a_secret); if(errid != 1){ printf("[ecdh_sharedS_secret]error!!!"); return -1; } printf("A shared_secret generation completed...\n"); errid = ecdh_shared_secret(a_pub,b_pri,b_secret); if(errid != 1){ printf("[ecdh_sharedS_secret]error!!!"); return -1; } printf("B shared_secret generation completed...\n"); hash_sha256(a_secret,a_hash); if(errid != 1){ printf("[hash_sha256]error!!!"); return -1; } printf("A shared_secret hash completed...\n"); hash_sha256(b_secret,b_hash); if(errid != 1){ printf("[hash_sha256]error!!!"); return -1; } printf("B shared_secret hash completed...\n"); /* sign */ errid = ecdsa_sign(a_pri,a_hash,p_signature); if(errid != 1){ printf("[ecdsa_sign]error!!!"); return -1; } /* verify */ errid = ecdsa_verify(a_pub,a_hash,p_signature); if(errid != 1){ printf("[ecdsa_verify]error!!!"); return -1; }else{ printf("success \n"); } errid = ecdsa_sign(b_pri,b_hash,p_signature); if(errid != 1){ printf("[ecdsa_sign]error!!!"); return -1; } /* verify */ errid = ecdsa_verify(b_pub,b_hash,p_signature); if(errid != 1){ printf("[ecdsa_verify]error!!!"); return -1; }else{ printf("success \n"); } return 0; }
END_TEST START_TEST(test_sign_speed) { uint8_t sig[64], priv_key[32], msg[256]; size_t i; int res; for (i = 0; i < sizeof(msg); i++) { msg[i] = i * 1103515245; } clock_t t = clock(); memcpy(priv_key, fromhex("c55ece858b0ddd5263f96810fe14437cd3b5e1fbd7c6a2ec1e031f05e86d8bd5"), 32); for (i = 0 ; i < 250; i++) { res = ecdsa_sign(priv_key, msg, sizeof(msg), sig); ck_assert_int_eq(res, 0); } memcpy(priv_key, fromhex("509a0382ff5da48e402967a671bdcde70046d07f0df52cff12e8e3883b426a0a"), 32); for (i = 0 ; i < 250; i++) { res = ecdsa_sign(priv_key, msg, sizeof(msg), sig); ck_assert_int_eq(res, 0); } printf("Signing speed: %0.2f sig/s\n", 500.0f / ((float)(clock() - t) / CLOCKS_PER_SEC)); }
/* * Certificate info: * - id: requester identification * - cname: common name * - time: date on which the certificate has been generated * - valid: date up to the certificate is valid * - auth_key: key used in mutual authentication (SMQV) * - token_key: key used to sign access token (MSS) * - signature: signature under issuer's key * */ void generate_certificate(const unsigned char csr[CSR_MAX_SIZE], const char valid[TIME_BUFFER_SIZE], const unsigned char ca_skey[ECDSA_SKEY_SIZE], unsigned char certificate[CERTIFICATE_MAX_SIZE]) { unsigned int id; char cname[CNAME_MAX_SIZE], time[TIME_BUFFER_SIZE]; unsigned char auth_key[SMQV_PKEY_SIZE], token_key[MSS_PKEY_SIZE], cert_signature[ECDSA_SIGNATURE_SIZE], csr_signature[MSS_SIGNATURE_SIZE]; unsigned char buffer[CERTIFICATE_MAX_SIZE]; memset(buffer, 0, CERTIFICATE_MAX_SIZE); now(&time); if(compare_dates(valid, time) == -1 && read_csr(&id, cname, time, auth_key, token_key, csr_signature, csr)) { unsigned int index = 0; index += cert_append_info(buffer, id, cname, time, valid, auth_key, token_key); unsigned char cert_digest[2 * MSS_SEC_LVL]; sponge_hash(buffer, index, cert_digest, 2 * MSS_SEC_LVL); ecdsa_sign(ca_skey, cert_digest, cert_signature); memcpy(buffer + index, cert_signature, ECDSA_SIGNATURE_SIZE); index += ECDSA_SIGNATURE_SIZE; base64encode(buffer, index, certificate, CSR_MAX_SIZE); } else{ certificate[0] = '\0'; if( compare_dates(valid, time) != -1) printf("Authentication ERROR: !(valid > t_now)\n"); else printf("Authentication ERROR: !mss_verify\n"); } }
//TODO: The fwrite/fread error checking was broken. //Maybe the MS runtime is returning the number of bytes written instead of the element count? BOOL __stdcall np_sign_file(s8 *fname) { u8 padding_data[0x10] = { 0xbc, 0x3f, 0x7a, 0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48 }; keyset_t *ks; FILE *fp = NULL; u8 *buffer = NULL; u32 length; u32 padding; u8 hash[0x14], R[0x15], S[0x15]; //Try to find keyset. if((ks = keyset_find_by_name(CONFIG_NP_SIG_KNAME)) == NULL) return FALSE; if((fp = fopen(fname, "r+b")) == NULL) return FALSE; fseek(fp, 0, SEEK_END); length = ftell(fp); padding = length % 0x10; if(padding > 0) { fwrite(padding_data, sizeof(u8), padding, fp); length += padding; } fseek(fp, 0, SEEK_SET); if((buffer = (u8 *)calloc(length, sizeof(char))) == NULL) { fclose(fp); return FALSE; } fread(buffer, sizeof(u8), length, fp); //Generate header hash. sha1(buffer, length, hash); //Generate signature. /* TODO: Set the right curve and private key */ ecdsa_set_curve(ks->ctype | USE_VSH_CURVE); ecdsa_set_pub(ks->pub); ecdsa_set_priv(ks->priv); ecdsa_sign(hash, R, S); fseek(fp, 0, SEEK_END); fwrite(R + 1, 0x14, 1, fp); fwrite(S + 1, 0x14, 1, fp); /* Let's be as stupid as sony here... */ fwrite(hash + 0xC, 8, 1, fp); free(buffer); fclose(fp); return TRUE; }
int add_npdrm_footer_sig(const char *filename) { FILE *fp; uint8_t s[21]; uint8_t r[21]; uint8_t hash[20]; static char padding[] = { 0x8b, 0x3f, 0x7a,0x48, 0xaf, 0x45, 0xef, 0x28, 0x3a, 0x05, 0x98, 0x10, 0xbc, 0x3f, 0x7a, 0x48 }; keyset_t *keyset = find_keyset_by_name("NP_sig"); if ( !keyset) return 0; fp = fopen(filename, "r+b"); if (!fp) return 0; fseek(fp, 0, SEEK_END); size_t size = ftell (fp); // Error ? SCETool takes left_not_aligned as (size & 0xF) size_t left_not_aligned = (0x10 - (size & 0xF)) & 0x0F; if (left_not_aligned) { fwrite(padding, 1, left_not_aligned, fp); size += left_not_aligned; } fseek(fp, 0, SEEK_SET); uint8_t *buffer = malloc(size); if (!buffer) { fclose(fp); return 0; } if(fread(buffer, 1, size, fp) != size) return 0; sha1(buffer, size, hash); ecdsa_set_curve(keyset->ctype | 0x40); ecdsa_set_pub(keyset->pub_key); ecdsa_set_priv(keyset->priv_key); ecdsa_sign(r, s, hash); fseek(fp, 0, SEEK_END); fwrite(&r[1], 20, 1, fp); fwrite(&s[1], 20, 1, fp); fwrite(&hash[12], 8, 1, fp); free(buffer); fclose(fp); return 1; }
int edata_sign_free(u8 *edata_buf, u8 *pgd_key) { MAC_KEY mkey; AES_ctx aes; u8 sha1_hash[20], license_key[16]; int flag, i; printf("re-sign EDATA ...\n"); flag = *(u8*)(edata_buf+15); // get license_key if(flag&1){ sceDrmBBMacInit(&mkey, 3); sceDrmBBMacUpdate(&mkey, edata_buf, 0x80); bbmac_getkey(&mkey, edata_buf+0x80, license_key); if(verbose) hex_dump("license key", license_key, 16); } // change to use free license *(u32*)(edata_buf+8) = 0x01000000; // build ecdsa ecdsa_set_curve(&ecdsa_app); ecdsa_set_priv(priv_key_edata); SHA1(edata_buf, 0x58, sha1_hash); ecdsa_sign(sha1_hash, edata_buf+0x58, edata_buf+0x6c, NULL); // build BBMAC if(flag&1){ sceDrmBBMacInit(&mkey, 3); sceDrmBBMacUpdate(&mkey, edata_buf, 0x80); sceDrmBBMacFinal(&mkey, edata_buf+0x80, license_key); bbmac_build_final2(3, edata_buf+0x80); } // build PGD key sceNpDrmGetFixedKey(pgd_key, (char*)(edata_buf+16), 0x01000000); if(verbose) hex_dump("get_fixed_key", pgd_key, 16); if(flag&1){ for(i=0; i<16; i++){ pgd_key[i] ^= license_key[i]; } } AES_set_key(&aes, edat_aeskey, 128); AES_decrypt(&aes, pgd_key, pgd_key); if(verbose) hex_dump("new PGD key", pgd_key, 16); return 0; }
static void bench_ecdsa_sign (void *p) { struct ecdsa_ctx *ctx = p; struct dsa_signature s; dsa_signature_init (&s); ecdsa_sign (&ctx->key, &ctx->rctx, (nettle_random_func *) knuth_lfib_random, ctx->digest_size, ctx->digest, &s); dsa_signature_clear (&s); }
static void sign_hdr(void) { u8 *r, *s; u8 hash[20]; u64 sig_len; sig_len = be64(self + meta_offset + 0x60); r = self + sig_len; s = r + 21; sha1(self, sig_len, hash); ecdsa_sign(hash, r, s); }
static void sign_hdr(void) { u8 *r, *s; u8 hash[20]; u64 sig_len; sig_len = be64(pkg + 0x60); r = pkg + sig_len; s = r + 21; sha1(pkg, sig_len, hash); ecdsa_sign(hash, r, s); }
int main(){ unsigned char key[48]; unsigned char pkey[96]; unsigned char digest[48]; unsigned char signature[96]; for(int i=0; i<1000; i++){ randombytes(key, 48); randombytes(digest, 48); key[47]=0; p384_32_scalarmult_base(pkey, key); ecdsa_sign(signature, digest, key); if(!ecdsa_verify(signature, digest, pkey)){ printf("Ecdsa failure to verify valid signature\n"); } digest[0]=digest[0]+1; if(ecdsa_verify(signature,digest,pkey)){ printf("Ecdsa failure to reject invalid signature\n"); } } }
// Send a SIGnature record, containing an ECDSA signature over both KEX records. static bool send_sig(sptps_t *s) { size_t keylen = ECDH_SIZE; size_t siglen = ecdsa_size(s->mykey); // Concatenate both KEX messages, plus tag indicating if it is from the connection originator, plus label char msg[(1 + 32 + keylen) * 2 + 1 + s->labellen]; char sig[siglen]; msg[0] = s->initiator; memcpy(msg + 1, s->mykex, 1 + 32 + keylen); memcpy(msg + 1 + 33 + keylen, s->hiskex, 1 + 32 + keylen); memcpy(msg + 1 + 2 * (33 + keylen), s->label, s->labellen); // Sign the result. if(!ecdsa_sign(s->mykey, msg, sizeof msg, sig)) return error(s, EINVAL, "Failed to sign SIG record"); // Send the SIG exchange record. return send_record_priv(s, SPTPS_HANDSHAKE, sig, sizeof sig); }
int main() { unsigned char skey[ECDSA_SKEY_SIZE], pkey[ECDSA_PKEY_SIZE], digest[ECDSA_DIGEST_SIZE], signature[ECDSA_SIGNATURE_SIZE]; printf("ECDSA key generation... "); ecdsa_keygen(skey, pkey); printf("done!\n"); Display("ECDSA skey:", skey, ECDSA_SKEY_SIZE); Display("ECDSA pkey:", pkey, ECDSA_PKEY_SIZE); printf("---------------\n"); Display("digest:", digest, ECDSA_DIGEST_SIZE); printf("ECDSA signature... "); ecdsa_sign(skey, digest, signature); printf("done!\n"); Display("signature:", signature, ECDSA_SIGNATURE_SIZE); printf("ECDSA verification... \n"); if(ecdsa_verify(pkey, digest, signature)) printf("ECDSA - OK\n"); else printf("ECDSA - FAIL\n"); return 0; }
static void bacast_signed_message() { msg_header_t* header; uint8_t* data; packetbuf_clear(); header = ( msg_header_t* ) ( packetbuf_dataptr() ); data = ( uint8_t* ) ( header + 1 ); random_data ( data, MSG_LEN ); hton_uint16 ( &header->data_len, MSG_LEN ); static struct etimer nrg; energest_flush(); ENERGEST_ON ( ENERGEST_TYPE_LPM ); ENERGEST_ON ( ENERGEST_TYPE_TRANSMIT ); ENERGEST_ON ( ENERGEST_TYPE_LISTEN ); ENERGEST_ON ( ENERGEST_TYPE_CPU ); last.cpu = energest_type_time ( ENERGEST_TYPE_CPU )/RTIMER_SECOND; ENERGEST_OFF ( ENERGEST_TYPE_CPU ); last.lpm = energest_type_time ( ENERGEST_TYPE_LPM ); last.transmit = energest_type_time ( ENERGEST_TYPE_TRANSMIT ); last.listen = energest_type_time ( ENERGEST_TYPE_LISTEN ); ENERGEST_ON ( ENERGEST_TYPE_CPU ); ecdsa_sign ( data, MSG_LEN, header->r, header->s, prKey_alice ); diff.cpu = energest_type_time ( ENERGEST_TYPE_CPU ) - last.cpu; diff.lpm = energest_type_time ( ENERGEST_TYPE_LPM ) - last.lpm; diff.transmit = energest_type_time ( ENERGEST_TYPE_TRANSMIT ) - last.transmit; diff.listen = energest_type_time ( ENERGEST_TYPE_LISTEN ) - last.listen; ENERGEST_OFF ( ENERGEST_TYPE_CPU ); ENERGEST_OFF ( ENERGEST_TYPE_LPM ); ENERGEST_OFF ( ENERGEST_TYPE_TRANSMIT ); ENERGEST_OFF ( ENERGEST_TYPE_LISTEN ); packetbuf_set_datalen ( sizeof ( msg_header_t ) + MSG_LEN ); abc_send ( &abc ); printf ( "Clock ticks recorded by\nCPU = %ld \nLPM = %ld \nTRANSMITTER = %ld\nRECEIVER = %ld\n",diff.cpu, diff.lpm, diff.transmit, diff.listen ); }
int main(int argc, char * argv[]) { uint8_t hash[SHA256_DIGEST_LENGTH] = {0}; NN_DIGIT signature_r[NUMWORDS], signature_s[NUMWORDS]; NN_DIGIT privKey[NUMWORDS]; point_t pubKey; uint8_t data [52] = { 1, 2, 3, 4, 5 }; SHA256_CTX ctx; memset(privKey, 0, NUMBYTES); memset(&pubKey, 0, sizeof(pubKey)); memset(signature_r, 0, NUMBYTES); memset(signature_s, 0, NUMBYTES); SHA256_Init(&ctx); SHA256_Update(&ctx, data, 52); SHA256_Final(hash, &ctx); ecc_init(); ecc_gen_private_key(privKey); ecc_gen_pub_key(privKey, &pubKey); ecdsa_init(&pubKey); ecdsa_sign(hash, signature_r, signature_s, privKey); assert(ecdsa_verify(hash, signature_r, signature_s, &pubKey) == 1); signature_r[0] ^= 0xff; assert(ecdsa_verify(hash, signature_r, signature_s, &pubKey) != 1); return 0; }
// func. to ECDSA sign the SPP sections int sign_spp(u8* pInSpp) { u8 *r, *s = NULL; u8 hash[20] = {0}; u64 sig_len = 0; mpi r1; mpi s1; int retval = -1; // validate input params if (pInSpp == NULL) goto exit; // init the mpi mpi_init(&r1); mpi_init(&s1); // setup the 'signature len' sig_len = be64(pInSpp + 0x60); r = pInSpp + sig_len; s = r + 21; // sha1 the hash sha1(pInSpp, (size_t)sig_len, hash); // ecdsa sign the hash if ( ecdsa_sign(&ecdsa_ctx.grp, (mpi*)&r1, (mpi*)&s1, &ecdsa_ctx.d, hash, ECDSA_KEYSIZE_PRIV, get_random_char, NULL) == STATUS_SUCCESS ) { mpi_write_binary(&r1, (unsigned char*)r, ECDSA_KEYSIZE_PRIV); mpi_write_binary(&s1, (unsigned char*)s, ECDSA_KEYSIZE_PRIV); // status success retval = STATUS_SUCCESS; } exit: return retval; }
static void * bench_ecdsa_init (unsigned size) { struct ecdsa_ctx *ctx; const struct ecc_curve *ecc; const char *xs; const char *ys; const char *zs; mpz_t x, y, z; ctx = xalloc (sizeof(*ctx)); dsa_signature_init (&ctx->s); knuth_lfib_init (&ctx->rctx, 17); switch (size) { case 192: ecc = &_nettle_secp_192r1; xs = "8e8e07360350fb6b7ad8370cfd32fa8c6bba785e6e200599"; ys = "7f82ddb58a43d59ff8dc66053002b918b99bd01bd68d6736"; zs = "f2e620e086d658b4b507996988480917640e4dc107808bdd"; ctx->digest = hash_string (&nettle_sha1, "abc"); ctx->digest_size = 20; break; case 224: ecc = &_nettle_secp_224r1; xs = "993bf363f4f2bc0f255f22563980449164e9c894d9efd088d7b77334"; ys = "b75fff9849997d02d135140e4d0030944589586e22df1fc4b629082a"; zs = "cdfd01838247f5de3cc70b688418046f10a2bfaca6de9ec836d48c27"; ctx->digest = hash_string (&nettle_sha224, "abc"); ctx->digest_size = 28; break; /* From RFC 4754 */ case 256: ecc = &_nettle_secp_256r1; xs = "2442A5CC 0ECD015F A3CA31DC 8E2BBC70 BF42D60C BCA20085 E0822CB0 4235E970"; ys = "6FC98BD7 E50211A4 A27102FA 3549DF79 EBCB4BF2 46B80945 CDDFE7D5 09BBFD7D"; zs = "DC51D386 6A15BACD E33D96F9 92FCA99D A7E6EF09 34E70975 59C27F16 14C88A7F"; ctx->digest = hash_string (&nettle_sha256, "abc"); ctx->digest_size = 32; break; case 384: ecc = &_nettle_secp_384r1; xs = "96281BF8 DD5E0525 CA049C04 8D345D30 82968D10 FEDF5C5A CA0C64E6 465A97EA" "5CE10C9D FEC21797 41571072 1F437922"; ys = "447688BA 94708EB6 E2E4D59F 6AB6D7ED FF9301D2 49FE49C3 3096655F 5D502FAD" "3D383B91 C5E7EDAA 2B714CC9 9D5743CA"; zs = "0BEB6466 34BA8773 5D77AE48 09A0EBEA 865535DE 4C1E1DCB 692E8470 8E81A5AF" "62E528C3 8B2A81B3 5309668D 73524D9F"; ctx->digest = hash_string (&nettle_sha384, "abc"); ctx->digest_size = 48; break; case 521: ecc = &_nettle_secp_521r1; xs = "0151518F 1AF0F563 517EDD54 85190DF9 5A4BF57B 5CBA4CF2 A9A3F647 4725A35F" "7AFE0A6D DEB8BEDB CD6A197E 592D4018 8901CECD 650699C9 B5E456AE A5ADD190" "52A8"; ys = "006F3B14 2EA1BFFF 7E2837AD 44C9E4FF 6D2D34C7 3184BBAD 90026DD5 E6E85317" "D9DF45CA D7803C6C 20035B2F 3FF63AFF 4E1BA64D 1C077577 DA3F4286 C58F0AEA" "E643"; zs = "0065FDA3 409451DC AB0A0EAD 45495112 A3D813C1 7BFD34BD F8C1209D 7DF58491" "20597779 060A7FF9 D704ADF7 8B570FFA D6F062E9 5C7E0C5D 5481C5B1 53B48B37" "5FA1"; ctx->digest = hash_string (&nettle_sha512, "abc"); ctx->digest_size = 64; break; default: die ("Internal error.\n"); } ecc_point_init (&ctx->pub, ecc); ecc_scalar_init (&ctx->key, ecc); mpz_init_set_str (x, xs, 16); mpz_init_set_str (y, ys, 16); mpz_init_set_str (z, zs, 16); ecc_point_set (&ctx->pub, x, y); ecc_scalar_set (&ctx->key, z); mpz_clear (x); mpz_clear (y); mpz_clear (z); ecdsa_sign (&ctx->key, &ctx->rctx, (nettle_random_func *) knuth_lfib_random, ctx->digest_size, ctx->digest, &ctx->s); return ctx; }
static void promptRegister(bool request, const U2F_REGISTER_REQ *req) { #if 0 // Users find it confusing when a Ledger and a KeepKey are plugged in // at the same time. To avoid that, we elect not to show a message in // this case. if (0 == memcmp(req->appId, BOGUS_APPID, U2F_APPID_SIZE)) { layoutU2FDialog(request, "U2f Register", "Another U2F device was used to register in this application."); } else { #else { #endif const char *appname = ""; bool readable = getReadableAppId(req->appId, &appname); layoutU2FDialog(request, "U2F Register", readable ? "Do you want to register with %s?" : "Do you want to register with this U2F application?\n\n%s", appname); } } void u2f_register(const APDU *a) { static U2F_REGISTER_REQ last_req; const U2F_REGISTER_REQ *req = (U2F_REGISTER_REQ *)a->data; if (!storage_isInitialized()) { layout_warning_static("Cannot register u2f: not initialized"); send_u2f_error(U2F_SW_CONDITIONS_NOT_SATISFIED); delay_ms(3000); return; } // Validate basic request parameters debugLog(0, "", "u2f register"); if (APDU_LEN(*a) != sizeof(U2F_REGISTER_REQ)) { debugLog(0, "", "u2f register - badlen"); send_u2f_error(U2F_SW_WRONG_LENGTH); return; } // If this request is different from last request, reset state machine if (memcmp(&last_req, req, sizeof(last_req)) != 0) { memcpy(&last_req, req, sizeof(last_req)); last_req_state = INIT; } // First Time request, return not present and display request dialog if (last_req_state == INIT) { // error: testof-user-presence is required //buttonUpdate(); promptRegister(true, req); last_req_state = REG; } // Still awaiting Keypress if (last_req_state == REG) { // error: testof-user-presence is required send_u2f_error(U2F_SW_CONDITIONS_NOT_SATISFIED); dialog_timeout = U2F_TIMEOUT; return; } // Buttons said yes if (last_req_state == REG_PASS) { uint8_t data[sizeof(U2F_REGISTER_RESP) + 2]; U2F_REGISTER_RESP *resp = (U2F_REGISTER_RESP *)&data; memzero(data, sizeof(data)); resp->registerId = U2F_REGISTER_ID; resp->keyHandleLen = KEY_HANDLE_LEN; // Generate keypair for this appId const HDNode *node = generateKeyHandle(req->appId, (uint8_t*)&resp->keyHandleCertSig); if (!node) { debugLog(0, "", "getDerivedNode Fail"); send_u2f_error(U2F_SW_WRONG_DATA); // error:bad key handle return; } ecdsa_get_public_key65(node->curve->params, node->private_key, (uint8_t *)&resp->pubKey); memcpy(resp->keyHandleCertSig + resp->keyHandleLen, U2F_ATT_CERT, sizeof(U2F_ATT_CERT)); uint8_t sig[64]; U2F_REGISTER_SIG_STR sig_base; sig_base.reserved = 0; memcpy(sig_base.appId, req->appId, U2F_APPID_SIZE); memcpy(sig_base.chal, req->chal, U2F_CHAL_SIZE); memcpy(sig_base.keyHandle, &resp->keyHandleCertSig, KEY_HANDLE_LEN); memcpy(sig_base.pubKey, &resp->pubKey, U2F_PUBKEY_LEN); if (ecdsa_sign(&nist256p1, HASHER_SHA2, U2F_ATT_PRIV_KEY, (uint8_t *)&sig_base, sizeof(sig_base), sig, NULL, NULL) != 0) { send_u2f_error(U2F_SW_WRONG_DATA); return; } // Where to write the signature in the response uint8_t *resp_sig = resp->keyHandleCertSig + resp->keyHandleLen + sizeof(U2F_ATT_CERT); // Convert to der for the response const uint8_t sig_len = ecdsa_sig_to_der(sig, resp_sig); // Append success bytes memcpy(resp->keyHandleCertSig + resp->keyHandleLen + sizeof(U2F_ATT_CERT) + sig_len, "\x90\x00", 2); int l = 1 /* registerId */ + U2F_PUBKEY_LEN + 1 /* keyhandleLen */ + resp->keyHandleLen + sizeof(U2F_ATT_CERT) + sig_len + 2; last_req_state = INIT; dialog_timeout = 0; send_u2f_msg(data, l); promptRegister(false, req); return; } // Didnt expect to get here dialog_timeout = 0; } static void promptAuthenticate(bool request, const U2F_AUTHENTICATE_REQ *req) { const char *appname = ""; bool readable = getReadableAppId(req->appId, &appname); layoutU2FDialog(request, "U2F Authenticate", readable ? "Log in to %s?" : "Do you want to log in?\n\n%s", appname); } void u2f_authenticate(const APDU *a) { const U2F_AUTHENTICATE_REQ *req = (U2F_AUTHENTICATE_REQ *)a->data; static U2F_AUTHENTICATE_REQ last_req; if (!storage_isInitialized()) { layout_warning_static("Cannot authenticate u2f: not initialized"); send_u2f_error(U2F_SW_CONDITIONS_NOT_SATISFIED); delay_ms(3000); return; } if (APDU_LEN(*a) < 64) { /// FIXME: decent value debugLog(0, "", "u2f authenticate - badlen"); send_u2f_error(U2F_SW_WRONG_LENGTH); return; } if (req->keyHandleLen != KEY_HANDLE_LEN) { debugLog(0, "", "u2f auth - bad keyhandle len"); send_u2f_error(U2F_SW_WRONG_DATA); // error:bad key handle return; } const HDNode *node = validateKeyHandle(req->appId, req->keyHandle); if (!node) { debugLog(0, "", "u2f auth - bad keyhandle len"); send_u2f_error(U2F_SW_WRONG_DATA); // error:bad key handle return; } if (a->p1 == U2F_AUTH_CHECK_ONLY) { debugLog(0, "", "u2f authenticate check"); // This is a success for a good keyhandle // A failed check would have happened earlier // error: testof-user-presence is required send_u2f_error(U2F_SW_CONDITIONS_NOT_SATISFIED); return; } if (a->p1 != U2F_AUTH_ENFORCE) { debugLog(0, "", "u2f authenticate unknown"); // error:bad key handle send_u2f_error(U2F_SW_WRONG_DATA); return; } debugLog(0, "", "u2f authenticate enforce"); if (memcmp(&last_req, req, sizeof(last_req)) != 0) { memcpy(&last_req, req, sizeof(last_req)); last_req_state = INIT; } if (last_req_state == INIT) { // error: testof-user-presence is required //buttonUpdate(); // Clear button state promptAuthenticate(true, req); last_req_state = AUTH; } // Awaiting Keypress if (last_req_state == AUTH) { // error: testof-user-presence is required send_u2f_error(U2F_SW_CONDITIONS_NOT_SATISFIED); dialog_timeout = U2F_TIMEOUT; return; } // Buttons said yes if (last_req_state == AUTH_PASS) { uint8_t buf[sizeof(U2F_AUTHENTICATE_RESP) + 2]; U2F_AUTHENTICATE_RESP *resp = (U2F_AUTHENTICATE_RESP *)&buf; const uint32_t ctr = storage_nextU2FCounter(); resp->flags = U2F_AUTH_FLAG_TUP; resp->ctr[0] = ctr >> 24 & 0xff; resp->ctr[1] = ctr >> 16 & 0xff; resp->ctr[2] = ctr >> 8 & 0xff; resp->ctr[3] = ctr & 0xff; // Build and sign response U2F_AUTHENTICATE_SIG_STR sig_base; uint8_t sig[64]; memcpy(sig_base.appId, req->appId, U2F_APPID_SIZE); sig_base.flags = resp->flags; memcpy(sig_base.ctr, resp->ctr, 4); memcpy(sig_base.chal, req->chal, U2F_CHAL_SIZE); if (ecdsa_sign(&nist256p1, HASHER_SHA2, node->private_key, (uint8_t *)&sig_base, sizeof(sig_base), sig, NULL, NULL) != 0) { send_u2f_error(U2F_SW_WRONG_DATA); return; } // Copy DER encoded signature into response const uint8_t sig_len = ecdsa_sig_to_der(sig, resp->sig); // Append OK memcpy(buf + sizeof(U2F_AUTHENTICATE_RESP) - U2F_MAX_EC_SIG_SIZE + sig_len, "\x90\x00", 2); last_req_state = INIT; dialog_timeout = 0; send_u2f_msg(buf, sizeof(U2F_AUTHENTICATE_RESP) - U2F_MAX_EC_SIG_SIZE + sig_len + 2); promptAuthenticate(false, req); } }
bool KeyPair::Sign(Signature& out, const Digest& hash) { return ecdsa_sign(privateKey, hash.Byte, out.Byte); }
/* in case of DSA puts into data, r,s */ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo, gnutls_datum_t * signature, const gnutls_datum_t * vdata, const gnutls_pk_params_st * pk_params) { int ret; unsigned int hash_len; const mac_entry_st *me; switch (algo) { case GNUTLS_PK_EC: /* we do ECDSA */ { struct ecc_scalar priv; struct dsa_signature sig; int curve_id = pk_params->flags; const struct ecc_curve *curve; curve = get_supported_curve(curve_id); if (curve == NULL) return gnutls_assert_val (GNUTLS_E_ECC_UNSUPPORTED_CURVE); ret = _ecc_params_to_privkey(pk_params, &priv, curve); if (ret < 0) return gnutls_assert_val(ret); dsa_signature_init(&sig); me = _gnutls_dsa_q_to_hash(algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert(); _gnutls_debug_log ("Security level of algorithm requires hash %s(%d) or better\n", _gnutls_mac_get_name(me), hash_len); hash_len = vdata->size; } ecdsa_sign(&priv, NULL, rnd_func, hash_len, vdata->data, &sig); ret = _gnutls_encode_ber_rs(signature, &sig.r, &sig.s); dsa_signature_clear(&sig); ecc_scalar_clear(&priv); if (ret < 0) { gnutls_assert(); goto cleanup; } break; } case GNUTLS_PK_DSA: { struct dsa_public_key pub; struct dsa_private_key priv; struct dsa_signature sig; memset(&priv, 0, sizeof(priv)); memset(&pub, 0, sizeof(pub)); _dsa_params_to_pubkey(pk_params, &pub); _dsa_params_to_privkey(pk_params, &priv); dsa_signature_init(&sig); me = _gnutls_dsa_q_to_hash(algo, pk_params, &hash_len); if (hash_len > vdata->size) { gnutls_assert(); _gnutls_debug_log ("Security level of algorithm requires hash %s(%d) or better\n", _gnutls_mac_get_name(me), hash_len); hash_len = vdata->size; } ret = _dsa_sign(&pub, &priv, NULL, rnd_func, hash_len, vdata->data, &sig); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIGN_FAILED; goto dsa_fail; } ret = _gnutls_encode_ber_rs(signature, &sig.r, &sig.s); dsa_fail: dsa_signature_clear(&sig); if (ret < 0) { gnutls_assert(); goto cleanup; } break; } case GNUTLS_PK_RSA: { struct rsa_private_key priv; struct rsa_public_key pub; mpz_t s; _rsa_params_to_privkey(pk_params, &priv); _rsa_params_to_pubkey(pk_params, &pub); mpz_init(s); ret = rsa_pkcs1_sign_tr(&pub, &priv, NULL, rnd_func, vdata->size, vdata->data, s); if (ret == 0) { gnutls_assert(); ret = GNUTLS_E_PK_SIGN_FAILED; goto rsa_fail; } ret = _gnutls_mpi_dprint_size(s, signature, pub.size); rsa_fail: mpz_clear(s); if (ret < 0) { gnutls_assert(); goto cleanup; } break; } default: gnutls_assert(); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = 0; cleanup: return ret; }
int main(int argc, char *argv[]) { ecdsa_t *key1, *key2; ecdh_t *ecdh1, *ecdh2; sptps_t sptps1, sptps2; char buf1[4096], buf2[4096], buf3[4096]; double duration = argc > 1 ? atof(argv[1]) : 10; crypto_init(); randomize(buf1, sizeof buf1); randomize(buf2, sizeof buf2); randomize(buf3, sizeof buf3); // Key generation fprintf(stderr, "Generating keys for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) ecdsa_free(ecdsa_generate()); fprintf(stderr, "%17.2lf op/s\n", rate); key1 = ecdsa_generate(); key2 = ecdsa_generate(); // Ed25519 signatures fprintf(stderr, "Ed25519 sign for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) if(!ecdsa_sign(key1, buf1, 256, buf2)) return 1; fprintf(stderr, "%20.2lf op/s\n", rate); fprintf(stderr, "Ed25519 verify for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) if(!ecdsa_verify(key1, buf1, 256, buf2)) { fprintf(stderr, "Signature verification failed\n"); return 1; } fprintf(stderr, "%18.2lf op/s\n", rate); ecdh1 = ecdh_generate_public(buf1); fprintf(stderr, "ECDH for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { ecdh2 = ecdh_generate_public(buf2); if(!ecdh2) return 1; if(!ecdh_compute_shared(ecdh2, buf1, buf3)) return 1; } fprintf(stderr, "%28.2lf op/s\n", rate); ecdh_free(ecdh1); // SPTPS authentication phase int fd[2]; if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) { fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno)); return 1; } struct pollfd pfd[2] = {{fd[0], POLLIN}, {fd[1], POLLIN}}; fprintf(stderr, "SPTPS/TCP authenticate for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record); sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record); while(poll(pfd, 2, 0)) { if(pfd[0].revents) receive_data(&sptps1); if(pfd[1].revents) receive_data(&sptps2); } sptps_stop(&sptps1); sptps_stop(&sptps2); } fprintf(stderr, "%10.2lf op/s\n", rate * 2); // SPTPS data sptps_start(&sptps1, fd + 0, true, false, key1, key2, "sptps_speed", 11, send_data, receive_record); sptps_start(&sptps2, fd + 1, false, false, key2, key1, "sptps_speed", 11, send_data, receive_record); while(poll(pfd, 2, 0)) { if(pfd[0].revents) receive_data(&sptps1); if(pfd[1].revents) receive_data(&sptps2); } fprintf(stderr, "SPTPS/TCP transmit for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { if(!sptps_send_record(&sptps1, 0, buf1, 1451)) abort(); receive_data(&sptps2); } rate *= 2 * 1451 * 8; if(rate > 1e9) fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9); else if(rate > 1e6) fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6); else if(rate > 1e3) fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3); sptps_stop(&sptps1); sptps_stop(&sptps2); // SPTPS datagram authentication phase close(fd[0]); close(fd[1]); if(socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) { fprintf(stderr, "Could not create a UNIX socket pair: %s\n", sockstrerror(sockerrno)); return 1; } fprintf(stderr, "SPTPS/UDP authenticate for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record); sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record); while(poll(pfd, 2, 0)) { if(pfd[0].revents) receive_data(&sptps1); if(pfd[1].revents) receive_data(&sptps2); } sptps_stop(&sptps1); sptps_stop(&sptps2); } fprintf(stderr, "%10.2lf op/s\n", rate * 2); // SPTPS datagram data sptps_start(&sptps1, fd + 0, true, true, key1, key2, "sptps_speed", 11, send_data, receive_record); sptps_start(&sptps2, fd + 1, false, true, key2, key1, "sptps_speed", 11, send_data, receive_record); while(poll(pfd, 2, 0)) { if(pfd[0].revents) receive_data(&sptps1); if(pfd[1].revents) receive_data(&sptps2); } fprintf(stderr, "SPTPS/UDP transmit for %lg seconds: ", duration); for(clock_start(); clock_countto(duration);) { if(!sptps_send_record(&sptps1, 0, buf1, 1451)) abort(); receive_data(&sptps2); } rate *= 2 * 1451 * 8; if(rate > 1e9) fprintf(stderr, "%14.2lf Gbit/s\n", rate / 1e9); else if(rate > 1e6) fprintf(stderr, "%14.2lf Mbit/s\n", rate / 1e6); else if(rate > 1e3) fprintf(stderr, "%14.2lf kbit/s\n", rate / 1e3); sptps_stop(&sptps1); sptps_stop(&sptps2); // Clean up close(fd[0]); close(fd[1]); ecdsa_free(key1); ecdsa_free(key2); crypto_exit(); return 0; }
void test_main (void) { unsigned i; struct knuth_lfib_ctx rctx; struct dsa_signature signature; struct tstring *digest; knuth_lfib_init (&rctx, 4711); dsa_signature_init (&signature); digest = SHEX (/* sha256("abc") */ "BA7816BF 8F01CFEA 414140DE 5DAE2223" "B00361A3 96177A9C B410FF61 F20015AD"); for (i = 0; ecc_curves[i]; i++) { const struct ecc_curve *ecc = ecc_curves[i]; struct ecc_point pub; struct ecc_scalar key; if (verbose) fprintf (stderr, "Curve %d\n", ecc->bit_size); ecc_point_init (&pub, ecc); ecc_scalar_init (&key, ecc); ecdsa_generate_keypair (&pub, &key, &rctx, (nettle_random_func *) knuth_lfib_random); if (verbose) { gmp_fprintf (stderr, "Public key:\nx = %Nx\ny = %Nx\n", pub.p, ecc->size, pub.p + ecc->size, ecc->size); gmp_fprintf (stderr, "Private key: %Nx\n", key.p, ecc->size); } if (!ecc_valid_p (&pub)) die ("ecdsa_generate_keypair produced an invalid point.\n"); ecdsa_sign (&key, &rctx, (nettle_random_func *) knuth_lfib_random, digest->length, digest->data, &signature); if (!ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify failed.\n"); digest->data[3] ^= 17; if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid digest.\n"); digest->data[3] ^= 17; mpz_combit (signature.r, 117); if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid signature.r.\n"); mpz_combit (signature.r, 117); mpz_combit (signature.s, 93); if (ecdsa_verify (&pub, digest->length, digest->data, &signature)) die ("ecdsa_verify returned success with invalid signature.s.\n"); ecc_point_clear (&pub); ecc_scalar_clear (&key); } dsa_signature_clear (&signature); }