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; }
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]; }
/** * 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); }
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; }
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 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); }
/** * 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; }
void sha256_update (sha256_context *cur, U8 *data, U32 len) { // If our current length is bigger than a block, just keep on // processing it until it isn't. while (len >= SHA_256_BLOCKSIZE) { sha256_process(cur, data); cur->bits += SHA_256_BLOCKSIZEBITS; data += SHA_256_BLOCKSIZE; len -= SHA_256_BLOCKSIZE; } // So we need to deal with whatever is leftover. We know the current // buffer location, and we want to store the smaller of the leftover // length or the rest of the buffer. Find that value and then store // the leftovers. if (len > 0) { U32 avail_space = len < SHA_256_BLOCKSIZE - cur->holdlength ? len : SHA_256_BLOCKSIZE - cur->holdlength; memcpy(&cur->buffer[cur->holdlength], data, avail_space); cur->holdlength += avail_space; data += avail_space; len -= avail_space; // If that just left our buffer with a full block, process it. if (cur->holdlength == SHA_256_BLOCKSIZE) { sha256_process(cur, cur->buffer); cur->bits += SHA_256_BLOCKSIZEBITS; cur->holdlength = 0; } } // Right now holdlength holds the leftover bytes that we need to process, // so be sure to increment our bit count. cur->bits += cur->holdlength * 8; }
/** * 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; }
void sha256_finish (sha256_context *cur, U8 *res ) { // We need to pad the start of our data with a 1 and the end of our // data with a bunch of zeroes cur->buffer[cur->holdlength++] = 0x80; // If our buffer holds more than 56 bytes (64-8) we are going to // pad it with zeros and shove it off for compression. if (cur->holdlength > SHA_256_BLOCKSIZE - 8) { memset(&cur->buffer[cur->holdlength++], (U8)0, (SHA_256_BLOCKSIZE - cur->holdlength)); sha256_process(cur, cur->buffer); cur->holdlength = 0; } // Prepare for the final compression step. Pad zeros until we have just // enough room to pad the number of bits onto the end. memset(&cur->buffer[cur->holdlength++], (U8)0, (56 - cur->holdlength)); // Pad our data with the length, fire off a transformation and we are // done! //TODO: Fix this, this is not as easy as it should be. U32 length_high = cur->bits >> 32; U32 length_low = cur->bits & 0xffffffff; U32_TO_U8(length_high, cur->buffer, 56); U32_TO_U8(length_low, cur->buffer, 60); sha256_process(cur, cur->buffer); // Transfer our result (in cur->state) to our result pointer. U8 i; for (i = 0; i <8; i++) { U32_TO_U8 (cur->state[i], res, i*4); } }
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(); }
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 }
static void sha256_process_wrap( void *ctx, const unsigned char *data ) { sha256_process( (sha256_context *) ctx, data ); }
/*---------------------------------------------------------------------------*/ 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(); }
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; }