/* Direct mapping from MD5 example in RFC2104 */ void hmac_sha256(struct hmac_sha256 *hmac, const void *key, size_t key_len, const void *text, size_t text_len) { struct sha256_ctx context; unsigned char k_ipad[65]; /* inner padding - * key XORd with ipad */ unsigned char k_opad[65]; /* outer padding - * key XORd with opad *//* start out by storing key in pads */ unsigned char tk[32]; int i; /* if key is longer than 64 bytes reset it to key=MD5(key) */ if (key_len > 64) { struct sha256_ctx tctx; sha256_init(&tctx); sha256_update(&tctx, key, key_len); sha256_done(&tctx, tk); key = tk; key_len = 32; } bzero( k_ipad, sizeof k_ipad); bzero( k_opad, sizeof k_opad); bcopy( key, k_ipad, key_len); bcopy( key, k_opad, key_len); /* XOR key with ipad and opad values */ for (i=0; i<64; i++) { k_ipad[i] ^= 0x36; k_opad[i] ^= 0x5c; } /* * perform inner MD5 */ sha256_init(&context); /* init context for 1st * pass */ sha256_update(&context, k_ipad, 64); /* start with inner pad */ sha256_update(&context, text, text_len); /* then text of datagram */ sha256_done(&context, &hmac->sha); /* finish up 1st pass */ /* * perform outer MD5 */ sha256_init(&context); /* init context for 2nd * pass */ sha256_update(&context, k_opad, 64); /* start with outer pad */ sha256_update(&context, &hmac->sha, 32); /* then results of 1st * hash */ sha256_done(&context, &hmac->sha); /* finish up 2nd pass */ }
/** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * @pScratchMem: Scratch memory; At least (108 + 288) = 396 bytes. */ void sha256_vector(void *priv, size_t num_elem, UINT8 *addr[], size_t * len, UINT8 *mac, UINT8 *pScratchMem) { UINT8 *pTmpBuf; size_t i; struct sha256_state *pCtx; /* ** sizeof(struct sha256_state) ** ** UINT64 length = 8 ** UINT32 state[8], curlen; = (9 * 4) = 36 ** UINT8 buf[64]; = 64 ** ----- ** 108 */ pCtx = (struct sha256_state *)pScratchMem; pTmpBuf = pScratchMem + sizeof(struct sha256_state); sha256_init(pCtx); for (i = 0; i < num_elem; i++) { /* pTmpBuf = At least 288 bytes of memory */ sha256_process((void *)priv, pCtx, addr[i], len[i], pTmpBuf); } sha256_done((void *)priv, pCtx, mac, pTmpBuf); }
String FileAccess::get_sha256(const String &p_file) { FileAccess *f = FileAccess::open(p_file, READ); if (!f) return String(); sha256_context sha256; sha256_init(&sha256); unsigned char step[32768]; while (true) { int br = f->get_buffer(step, 32768); if (br > 0) { sha256_hash(&sha256, step, br); } if (br < 4096) break; } unsigned char hash[32]; sha256_done(&sha256, hash); memdelete(f); return String::hex_encode_buffer(hash, 32); }
static int _sha256(unsigned char *hash, const unsigned char *data, const int datalen) { hash_state md; sha256_init(&md); sha256_process(&md, data, datalen); sha256_done(&md, hash); return CRYPT_OK; }
bool ClientPuzzleManager::checkOneSolution(U32 solution, Nonce &clientNonce, Nonce &serverNonce, U32 puzzleDifficulty, U32 clientIdentity) { U8 buffer[8]; writeU32ToBuffer(solution, buffer); writeU32ToBuffer(clientIdentity, buffer + 4); hash_state hashState; U8 hash[32]; sha256_init(&hashState); sha256_process(&hashState, buffer, sizeof(buffer)); sha256_process(&hashState, clientNonce.data, Nonce::NonceSize); sha256_process(&hashState, serverNonce.data, Nonce::NonceSize); sha256_done(&hashState, hash); U32 index = 0; while(puzzleDifficulty > 8) { if(hash[index]) return false; index++; puzzleDifficulty -= 8; } U8 mask = 0xFF << (8 - puzzleDifficulty); return (mask & hash[index]) == 0; }
void sha256(unsigned char* in, size_t in_size, unsigned char* out) { hash_state h; sha256_init(&h); sha256_process(&h, in, (unsigned long)in_size); sha256_done(&h, out); }
void hmac_sha256_done(struct hmac_sha256_ctx *ctx, struct hmac_sha256 *hmac) { /* (4) apply H to the stream generated in step (3) */ sha256_done(&ctx->sha, &hmac->sha); /* * (6) append the H result from step (4) to the B byte string * resulting from step (5) * (7) apply H to the stream generated in step (6) and output * the result */ sha256_init(&ctx->sha); sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad)); sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha)); sha256_done(&ctx->sha, &hmac->sha); }
void sha256_buffer(const unsigned char *buffer, size_t len, unsigned char hash[32]) { sha256_state md; sha256_init(&md); sha256_process(&md, buffer, len); sha256_done(&md, hash); }
void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data, size_t DataLength,byte *ResDigest) { const size_t Sha256BlockSize=64; // As defined in RFC 4868. byte KeyHash[SHA256_DIGEST_SIZE]; if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash. { sha256_context KCtx; sha256_init(&KCtx); sha256_process(&KCtx, Key, KeyLength); sha256_done(&KCtx, KeyHash); Key = KeyHash; KeyLength = SHA256_DIGEST_SIZE; } byte KeyBuf[Sha256BlockSize]; // Store the padded key here. for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest. KeyBuf[I] = Key[I] ^ 0x36; for (size_t I = KeyLength; I < Sha256BlockSize; I++) KeyBuf[I] = 0x36; sha256_context ICtx; sha256_init(&ICtx); sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key. sha256_process(&ICtx, Data, DataLength); // Hash data. byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data. sha256_done(&ICtx, IDig); sha256_context RCtx; sha256_init(&RCtx); for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding. KeyBuf[I] = Key[I] ^ 0x5c; for (size_t I = KeyLength; I < Sha256BlockSize; I++) KeyBuf[I] = 0x5c; sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key. sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest. sha256_done(&RCtx, ResDigest); }
int HashSHA256 (uint8 *value, int len, uint8* hashcode) { sha256_state sha256State; sha256_init(&sha256State); sha256_process(&sha256State, value, len); sha256_done(&sha256State, hashcode); return 0; }
/** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash */ void sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { struct sha256_state ctx; size_t i; sha256_init(&ctx); for (i = 0; i < num_elem; i++) sha256_process(&ctx, addr[i], len[i]); sha256_done(&ctx, mac); }
static void sha_with_seed(const unsigned char secret[32], unsigned char seed, struct sha256 *res) { struct sha256_ctx ctx; sha256_init(&ctx); sha256_update(&ctx, memcheck(secret, 32), 32); sha256_u8(&ctx, seed); sha256_done(&ctx, res); }
/** * SHA256 Hashing * @addr: pointers to the data area * @len: Lengths of the data block * @res: Buffer for the digest * Returns: 0 on success, -1 of failure */ int sha256(const unsigned char *addr, const size_t len, unsigned char *res) { struct sha256_state ctx; sha256_init(&ctx); if (sha256_process(&ctx, addr, len) || sha256_done(&ctx, res)) return -1; return 0; }
U32 NetInterface::computeClientIdentityToken(const Address &address, const Nonce &theNonce) { hash_state hashState; U32 hash[8]; sha256_init(&hashState); sha256_process(&hashState, (const U8 *) &address, sizeof(Address)); sha256_process(&hashState, theNonce.data, Nonce::NonceSize); sha256_process(&hashState, mRandomHashData, sizeof(mRandomHashData)); sha256_done(&hashState, (U8 *) hash); return hash[0]; }
/* BOLT #1: * * sending-key: SHA256(shared-secret || sending-node-session-pubkey) * * receiving-key: SHA256(shared-secret || receiving-node-session-pubkey) */ static struct enckey enckey_from_secret(const unsigned char secret[32], const unsigned char serial_pubkey[33]) { struct sha256_ctx ctx; struct enckey enckey; sha256_init(&ctx); sha256_update(&ctx, memcheck(secret, 32), 32); sha256_update(&ctx, memcheck(serial_pubkey, 33), 33); sha256_done(&ctx, &enckey.k); return enckey; }
/** * sha256_vector - SHA256 hash for data vector * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks * @mac: Buffer for the hash * Returns: 0 on success, -1 of failure */ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { struct sha256_state ctx; size_t i; sha256_init(&ctx); for (i = 0; i < num_elem; i++) if (sha256_process(&ctx, addr[i], len[i])) return -1; if (sha256_done(&ctx, mac)) return -1; return 0; }
string digest256(char const * data, size_t dataSize, bool returnAsHexString) { hash_state md; unsigned char out[256/8] = { 0 }; if (CRYPT_OK == sha256_init(&md) && CRYPT_OK == sha256_process(&md, reinterpret_cast<unsigned char const *>(data), dataSize) && CRYPT_OK == sha256_done(&md, out)) { if (returnAsHexString) return ToHex(string(reinterpret_cast<char const *>(out), ARRAY_SIZE(out))); else return string(reinterpret_cast<char const *>(out), ARRAY_SIZE(out)); } return string(); }
/** Terminate the hash to get the digest @param md The hash state @param out [out] The destination of the hash (28 bytes) @return CRYPT_OK if successful */ int sha224_done(hash_state * md, unsigned char *out) { unsigned char buf[32]; int err; LTC_ARGCHK(md != NULL); LTC_ARGCHK(out != NULL); err = sha256_done(md, buf); XMEMCPY(out, buf, 28); #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return err; }
int main(void) { struct sha256 h; struct sha256_ctx ctx; /* This is how many tests you plan to run */ plan_tests(1); ctx = after_16M_by_64; sha256_done(&ctx, &h); ok1(memcmp(&h.u, expected, sizeof(expected)) == 0); /* This exits depending on whether all tests passed */ return exit_status(); }
static bool do_test(const struct test *t) { struct sha256 h, expected; if (t->repetitions == 1) sha256(&h, t->test, strlen(t->test)); else { struct sha256_ctx ctx = SHA256_INIT; size_t i; for (i = 0; i < t->repetitions; i++) sha256_update(&ctx, t->test, strlen(t->test)); sha256_done(&ctx, &h); } hex_decode(t->result, strlen(t->result), &expected, sizeof(expected)); return memcmp(&h, &expected, sizeof(h)) == 0; }
int yacl_sha256_file (FILE *fp, uint8_t *out) { struct sha256_state state; sha256_init(&state); int c; int rc = -1; /* Perform the hash */ while ((c = getc (fp)) != EOF) { rc = sha256_process (&state, &c, sizeof c); if (rc) goto OUT; } sha256_done (&state, out); rc = 0; OUT: return rc; }
/*---------------------------------------------------------------------------*/ static void at_cmd_sha256_callback(struct at_cmd *cmd, uint8_t len, char *data) { /* Format: AT&SHA256=s, where s is a string up to 64 bytes */ uint8_t i; char tmp[4], sha256[32], sha256_res[64]; static sha256_state_t state; crypto_init(); if(sha256_init(&state) != CRYPTO_SUCCESS) { AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); return; } if(sha256_process(&state, &data[10], len - (cmd->cmd_hdr_len)) != CRYPTO_SUCCESS) { AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); return; } if(sha256_done(&state, sha256) != CRYPTO_SUCCESS) { AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); return; } crypto_disable(); PRINTF("Input: %s:\n", &data[10]); snprintf(tmp, 3, "%02X", sha256[0]); strncpy(sha256_res, tmp, 3); for(i = 1; i < 32; i++) { PRINTF("0x%02X ", sha256[i]); snprintf(tmp, 3, "%02X", sha256[i]); strcat(sha256_res, tmp); } PRINTF("\nSHA256: %s\n", sha256_res); AT_RESPONSE(sha256_res); AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); }
/** Self-test the hash @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled */ int sha256_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else static const struct { char *msg; unsigned char hash[32]; } tests[] = { { "abc", { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, }; int i; unsigned char tmp[32]; hash_state md; for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { sha256_init(&md); sha256_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg)); sha256_done(&md, tmp); if (memcmp(tmp, tests[i].hash, 32) != 0) { return CRYPT_FAIL_TESTVECTOR; } } return CRYPT_OK; #endif }
/*---------------------------------------------------------------------------*/ PROCESS_THREAD(sha256_test_process, ev, data) { static const char *const str_res[] = { "success", "invalid param", "NULL error", "resource in use", "DMA bus error" }; static const struct { const char *data[3]; uint8_t sha256[32]; } vectors[] = { { /* Simple */ { "abc", NULL, NULL }, { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad } }, { /* Simple */ { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL, NULL, }, { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, { /* Message of length 130 */ { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", NULL, NULL }, { 0x15, 0xd2, 0x3e, 0xea, 0x57, 0xb3, 0xd4, 0x61, 0xbf, 0x38, 0x91, 0x12, 0xab, 0x4c, 0x43, 0xce, 0x85, 0xe1, 0x68, 0x23, 0x8a, 0xaa, 0x54, 0x8e, 0xc8, 0x6f, 0x0c, 0x9d, 0x65, 0xf9, 0xb9, 0x23 } }, { /* Message of length 128 */ { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", NULL, NULL }, { 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f } }, { /* Message of length 64 */ { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", NULL, NULL }, { 0x2f, 0xcd, 0x5a, 0x0d, 0x60, 0xe4, 0xc9, 0x41, 0x38, 0x1f, 0xcc, 0x4e, 0x00, 0xa4, 0xbf, 0x8b, 0xe4, 0x22, 0xc3, 0xdd, 0xfa, 0xfb, 0x93, 0xc8, 0x09, 0xe8, 0xd1, 0xe2, 0xbf, 0xff, 0xae, 0x8e } }, { /* Message of length 66 */ { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", NULL, NULL }, { 0x92, 0x90, 0x1c, 0x85, 0x82, 0xe3, 0x1c, 0x05, 0x69, 0xb5, 0x36, 0x26, 0x9c, 0xe2, 0x2c, 0xc8, 0x30, 0x8b, 0xa4, 0x17, 0xab, 0x36, 0xc1, 0xbb, 0xaf, 0x08, 0x4f, 0xf5, 0x8b, 0x18, 0xdc, 0x6a } }, { { "abcdbcdecdefde", "fgefghfghighijhijkijkljklmklmnlmnomnopnopq", NULL }, { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 } }, { { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", NULL }, { 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f } }, { { "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh", "ijkl", "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" }, { 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f } } }; static sha256_state_t state; static uint8_t sha256[32]; static int i, j; static uint8_t ret; static rtimer_clock_t total_time; rtimer_clock_t time; size_t len; PROCESS_BEGIN(); puts("-----------------------------------------\n" "Initializing cryptoprocessor..."); crypto_init(); for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { printf("-----------------------------------------\n" "Test vector #%d:\n", i); time = RTIMER_NOW(); ret = sha256_init(&state); time = RTIMER_NOW() - time; total_time = time; printf("sha256_init(): %s, %lu us\n", str_res[ret], (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); PROCESS_PAUSE(); if(ret != CRYPTO_SUCCESS) { continue; } for(j = 0; j < sizeof(vectors[i].data) / sizeof(vectors[i].data[0]) && vectors[i].data[j] != NULL; j++) { len = strlen(vectors[i].data[j]); printf("Buffer #%d (length: %u):\n", j, len); time = RTIMER_NOW(); ret = sha256_process(&state, vectors[i].data[j], len); time = RTIMER_NOW() - time; total_time += time; printf("sha256_process(): %s, %lu us\n", str_res[ret], (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); PROCESS_PAUSE(); if(ret != CRYPTO_SUCCESS) { break; } } if(ret != CRYPTO_SUCCESS) { continue; } time = RTIMER_NOW(); ret = sha256_done(&state, sha256); time = RTIMER_NOW() - time; total_time += time; printf("sha256_done(): %s, %lu us\n", str_res[ret], (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); PROCESS_PAUSE(); if(ret != CRYPTO_SUCCESS) { continue; } if(rom_util_memcmp(sha256, vectors[i].sha256, sizeof(sha256))) { puts("Computed SHA-256 hash does not match expected hash"); } else { puts("Computed SHA-256 hash OK"); } printf("Total duration: %lu us\n", (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); } puts("-----------------------------------------\n" "Disabling cryptoprocessor..."); crypto_disable(); puts("Done!"); PROCESS_END(); }
sha256_double::sha256_double(sha256_ctx &shactx) { sha256_done(&shactx, &sha); sha256(&sha, &sha, sizeof(sha)); }
static void hmac_sha256(const byte *Key,size_t KeyLength,const byte *Data, size_t DataLength,byte *ResDigest, sha256_context *ICtxOpt,bool *SetIOpt, sha256_context *RCtxOpt,bool *SetROpt) { const size_t Sha256BlockSize=64; // As defined in RFC 4868. byte KeyHash[SHA256_DIGEST_SIZE]; if (KeyLength > Sha256BlockSize) // Convert longer keys to key hash. { sha256_context KCtx; sha256_init(&KCtx); sha256_process(&KCtx, Key, KeyLength); sha256_done(&KCtx, KeyHash); Key = KeyHash; KeyLength = SHA256_DIGEST_SIZE; } byte KeyBuf[Sha256BlockSize]; // Store the padded key here. sha256_context ICtx; if (ICtxOpt!=NULL && *SetIOpt) ICtx=*ICtxOpt; // Use already calculated first block context. else { // This calculation is the same for all iterations with same password. // So for PBKDF2 we can calculate it only for first block and then reuse // to improve performance. for (size_t I = 0; I < KeyLength; I++) // Use 0x36 padding for inner digest. KeyBuf[I] = Key[I] ^ 0x36; for (size_t I = KeyLength; I < Sha256BlockSize; I++) KeyBuf[I] = 0x36; sha256_init(&ICtx); sha256_process(&ICtx, KeyBuf, Sha256BlockSize); // Hash padded key. } if (ICtxOpt!=NULL && !*SetIOpt) // Store constant context for further reuse. { *ICtxOpt=ICtx; *SetIOpt=true; } sha256_process(&ICtx, Data, DataLength); // Hash data. byte IDig[SHA256_DIGEST_SIZE]; // Internal digest for padded key and data. sha256_done(&ICtx, IDig); sha256_context RCtx; if (RCtxOpt!=NULL && *SetROpt) RCtx=*RCtxOpt; // Use already calculated first block context. else { // This calculation is the same for all iterations with same password. // So for PBKDF2 we can calculate it only for first block and then reuse // to improve performance. for (size_t I = 0; I < KeyLength; I++) // Use 0x5c for outer key padding. KeyBuf[I] = Key[I] ^ 0x5c; for (size_t I = KeyLength; I < Sha256BlockSize; I++) KeyBuf[I] = 0x5c; sha256_init(&RCtx); sha256_process(&RCtx, KeyBuf, Sha256BlockSize); // Hash padded key. } if (RCtxOpt!=NULL && !*SetROpt) // Store constant context for further reuse. { *RCtxOpt=RCtx; *SetROpt=true; } sha256_process(&RCtx, IDig, SHA256_DIGEST_SIZE); // Hash internal digest. sha256_done(&RCtx, ResDigest); }
/** * u2fs_registration_verify: * @ctx: a context handle, from u2fs_init(). * @response: a U2F registration response message Base64 encoded. * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd. * * Get a U2F registration response and check its validity. * * Returns: On success %U2FS_OK (integer 0) is returned and @output is filled up with the user public key, the key handle and the attestation certificate. On errors * a #u2fs_rc error code. */ u2fs_rc u2fs_registration_verify(u2fs_ctx_t * ctx, const char *response, u2fs_reg_res_t ** output) { char *registrationData; char *clientData; char *clientData_decoded; unsigned char *user_public_key; size_t keyHandle_len; char *keyHandle; char *origin; char *challenge; char buf[_B64_BUFSIZE]; unsigned char c = 0; u2fs_X509_t *attestation_certificate; u2fs_ECDSA_t *signature; u2fs_EC_KEY_t *key; u2fs_rc rc; if (ctx == NULL || response == NULL || output == NULL) return U2FS_MEMORY_ERROR; key = NULL; clientData_decoded = NULL; challenge = NULL; origin = NULL; attestation_certificate = NULL; user_public_key = NULL; signature = NULL; registrationData = NULL; clientData = NULL; keyHandle = NULL; *output = NULL; rc = parse_registration_response(response, ®istrationData, &clientData); if (rc != U2FS_OK) goto failure; if (debug) { fprintf(stderr, "registrationData: %s\n", registrationData); fprintf(stderr, "clientData: %s\n", clientData); } rc = parse_registrationData(registrationData, &user_public_key, &keyHandle_len, &keyHandle, &attestation_certificate, &signature); if (rc != U2FS_OK) goto failure; rc = extract_EC_KEY_from_X509(attestation_certificate, &key); if (rc != U2FS_OK) goto failure; //TODO Add certificate validation rc = decode_clientData(clientData, &clientData_decoded); if (rc != U2FS_OK) goto failure; rc = parse_clientData(clientData_decoded, &challenge, &origin); if (rc != U2FS_OK) goto failure; if (strcmp(ctx->challenge, challenge) != 0) { rc = U2FS_CHALLENGE_ERROR; goto failure; } if (strcmp(ctx->origin, origin) != 0) { rc = U2FS_ORIGIN_ERROR; goto failure; } struct sha256_state sha_ctx; char challenge_parameter[U2FS_HASH_LEN], application_parameter[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) ctx->appid, strlen(ctx->appid)); sha256_done(&sha_ctx, (unsigned char *) application_parameter); sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) clientData_decoded, strlen(clientData_decoded)); sha256_done(&sha_ctx, (unsigned char *) challenge_parameter); unsigned char dgst[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, &c, 1); sha256_process(&sha_ctx, (unsigned char *) application_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) challenge_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) keyHandle, keyHandle_len); sha256_process(&sha_ctx, user_public_key, U2FS_PUBLIC_KEY_LEN); sha256_done(&sha_ctx, dgst); rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, key); if (rc != U2FS_OK) goto failure; free_sig(signature); signature = NULL; *output = calloc(1, sizeof(**output)); if (*output == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } rc = encode_b64u(keyHandle, keyHandle_len, buf); if (rc != U2FS_OK) goto failure; u2fs_EC_KEY_t *key_ptr; (*output)->keyHandle = strndup(buf, strlen(buf)); rc = decode_user_key(user_public_key, &key_ptr); if (rc != U2FS_OK) goto failure; (*output)->attestation_certificate = dup_cert(attestation_certificate); rc = dump_user_key(key_ptr, &(*output)->publicKey); if (rc != U2FS_OK) goto failure; rc = dump_X509_cert(attestation_certificate, &(*output)->attestation_certificate_PEM); if (rc != U2FS_OK) goto failure; if ((*output)->keyHandle == NULL || (*output)->publicKey == NULL || (*output)->attestation_certificate == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } free_key(key); key = NULL; free_cert(attestation_certificate); attestation_certificate = NULL; free(clientData_decoded); clientData_decoded = NULL; free(challenge); challenge = NULL; free(origin); origin = NULL; free(user_public_key); user_public_key = NULL; free(registrationData); registrationData = NULL; free(clientData); clientData = NULL; free(keyHandle); keyHandle = NULL; return U2FS_OK; failure: if (key) { free_key(key); key = NULL; } if (clientData_decoded) { free(clientData_decoded); clientData_decoded = NULL; } if (challenge) { free(challenge); challenge = NULL; } if (origin) { free(origin); origin = NULL; } if (attestation_certificate) { free_cert(attestation_certificate); attestation_certificate = NULL; } if (user_public_key) { free(user_public_key); user_public_key = NULL; } if (signature) { free_sig(signature); signature = NULL; } if (registrationData) { free(registrationData); registrationData = NULL; } if (clientData) { free(clientData); clientData = NULL; } if (keyHandle) { free(keyHandle); keyHandle = NULL; } return rc; }
/** * u2fs_authentication_verify: * @ctx: a context handle, from u2fs_init() * @response: pointer to output string with JSON data. * @output: pointer to output structure containing the relevant data for a well formed request. Memory should be free'd. * * Get a U2F authentication response and check its validity. * * Returns: On a successful verification %U2FS_OK (integer 0) is returned and @output is filled with the authentication result (same as the returned value), the counter received from the token and the user presence information. On errors * a #u2fs_rc error code is returned. */ u2fs_rc u2fs_authentication_verify(u2fs_ctx_t * ctx, const char *response, u2fs_auth_res_t ** output) { char *signatureData; char *clientData; char *clientData_decoded; char *keyHandle; char *challenge; char *origin; uint8_t user_presence; uint32_t counter_num; uint32_t counter; u2fs_ECDSA_t *signature; u2fs_rc rc; if (ctx == NULL || response == NULL || output == NULL) return U2FS_MEMORY_ERROR; signatureData = NULL; clientData = NULL; clientData_decoded = NULL; keyHandle = NULL; challenge = NULL; origin = NULL; signature = NULL; *output = NULL; rc = parse_authentication_response(response, &signatureData, &clientData, &keyHandle); if (rc != U2FS_OK) goto failure; if (debug) { fprintf(stderr, "signatureData: %s\n", signatureData); fprintf(stderr, "clientData: %s\n", clientData); fprintf(stderr, "keyHandle: %s\n", keyHandle); } rc = parse_signatureData(signatureData, &user_presence, &counter, &signature); if (rc != U2FS_OK) goto failure; rc = decode_clientData(clientData, &clientData_decoded); if (rc != U2FS_OK) goto failure; rc = parse_clientData(clientData_decoded, &challenge, &origin); if (rc != U2FS_OK) goto failure; if (strcmp(ctx->challenge, challenge) != 0) { rc = U2FS_CHALLENGE_ERROR; goto failure; } if (strcmp(ctx->origin, origin) != 0) { rc = U2FS_ORIGIN_ERROR; goto failure; } struct sha256_state sha_ctx; char challenge_parameter[U2FS_HASH_LEN], application_parameter[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) ctx->appid, strlen(ctx->appid)); sha256_done(&sha_ctx, (unsigned char *) application_parameter); sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) clientData_decoded, strlen(clientData_decoded)); sha256_done(&sha_ctx, (unsigned char *) challenge_parameter); unsigned char dgst[U2FS_HASH_LEN]; sha256_init(&sha_ctx); sha256_process(&sha_ctx, (unsigned char *) application_parameter, U2FS_HASH_LEN); sha256_process(&sha_ctx, (unsigned char *) &user_presence, 1); sha256_process(&sha_ctx, (unsigned char *) &counter, U2FS_COUNTER_LEN); sha256_process(&sha_ctx, (unsigned char *) challenge_parameter, U2FS_HASH_LEN); sha256_done(&sha_ctx, dgst); rc = verify_ECDSA(dgst, U2FS_HASH_LEN, signature, ctx->key); if (rc != U2FS_OK) goto failure; free_sig(signature); signature = NULL; *output = calloc(1, sizeof(**output)); if (*output == NULL) { rc = U2FS_MEMORY_ERROR; goto failure; } counter_num = 0; counter_num |= (counter & 0xFF000000) >> 24; counter_num |= (counter & 0x00FF0000) >> 8; counter_num |= (counter & 0x0000FF00) << 8; counter_num |= (counter & 0x000000FF) << 24; (*output)->verified = U2FS_OK; (*output)->user_presence = user_presence; (*output)->counter = counter_num; free(origin); origin = NULL; free(challenge); challenge = NULL; free(keyHandle); keyHandle = NULL; free(signatureData); signatureData = NULL; free(clientData); clientData = NULL; free(clientData_decoded); clientData_decoded = NULL; return U2FS_OK; failure: if (clientData_decoded) { free(clientData_decoded); clientData_decoded = NULL; } if (challenge) { free(challenge); challenge = NULL; } if (origin) { free(origin); origin = NULL; } if (signature) { free_sig(signature); signature = NULL; } if (signatureData) { free(signatureData); signatureData = NULL; } if (clientData) { free(clientData); clientData = NULL; } if (keyHandle) { free(keyHandle); keyHandle = NULL; } return rc; }