static void insert_message_authenticator(struct rad_handle *h, int resp) { #ifdef WITH_SSL u_char md[EVP_MAX_MD_SIZE]; u_int md_len; const struct rad_server *srvp; HMAC_CTX ctx; srvp = &h->servers[h->srv]; if (h->authentic_pos != 0) { HMAC_CTX_init(&ctx); HMAC_Init(&ctx, srvp->secret, strlen(srvp->secret), EVP_md5()); HMAC_Update(&ctx, &h->out[POS_CODE], POS_AUTH - POS_CODE); if (resp) HMAC_Update(&ctx, &h->in[POS_AUTH], LEN_AUTH); else HMAC_Update(&ctx, &h->out[POS_AUTH], LEN_AUTH); HMAC_Update(&ctx, &h->out[POS_ATTRS], h->out_len - POS_ATTRS); HMAC_Final(&ctx, md, &md_len); HMAC_CTX_cleanup(&ctx); HMAC_cleanup(&ctx); memcpy(&h->out[h->authentic_pos + 2], md, md_len); } #endif }
Hmac_sha1_state::~Hmac_sha1_state () { // Note: Explicit destructor necessary because class contains an auto_ptr // which contains an incomplete type when the auto_ptr is declared. HMAC_cleanup(&(impl->ctx)); }
void openssl_hmac_md5() { int fd, size; unsigned int len; HMAC_CTX hmac_ctx; char file_name[COMM_LEN], inputs[COMM_LEN]; unsigned char tmps[LINE_LEN], outputs[EVP_MAX_MD_SIZE]; memset(tmps, 0, sizeof(tmps)); memset(inputs, 0, sizeof(inputs)); memset(outputs, 0, sizeof(outputs)); printf("\nPlease input a file name: "); scanf("%s", file_name); fd = open(file_name, O_RDONLY); if (fd < 0) return; OpenSSL_add_all_digests(); strcpy(inputs, "hmac_md5"); HMAC_Init(&hmac_ctx, inputs, sizeof(inputs), EVP_get_digestbyname("md5")); while ((size = read(fd, tmps, LINE_LEN)) > 0) HMAC_Update(&hmac_ctx, tmps, size); HMAC_Final(&hmac_ctx, outputs, &len); HMAC_cleanup(&hmac_ctx); close(fd); printf("HMAC_MD5(%s, %s) = ", file_name, inputs); for (size = 0; size < len; size++) printf("%02x", outputs[size]); printf("\n"); }
void mac_clear(Mac *mac) { if (mac->evp_md != NULL) HMAC_cleanup(&mac->evp_ctx); mac->evp_md = NULL; }
static void tls1_P_hash(const EVP_MD *md, const unsigned char *sec, int sec_len, unsigned char *seed, int seed_len, unsigned char *out, int olen) { int chunk,n; unsigned int j; HMAC_CTX ctx; HMAC_CTX ctx_tmp; unsigned char A1[HMAC_MAX_MD_CBLOCK]; unsigned int A1_len; chunk=EVP_MD_size(md); HMAC_Init(&ctx,sec,sec_len,md); HMAC_Update(&ctx,seed,seed_len); HMAC_Final(&ctx,A1,&A1_len); n=0; for (;;) { HMAC_Init(&ctx,NULL,0,NULL); /* re-init */ HMAC_Update(&ctx,A1,A1_len); memcpy(&ctx_tmp,&ctx,sizeof(ctx)); /* Copy for A2 */ /* not needed for last one */ HMAC_Update(&ctx,seed,seed_len); if (olen > chunk) { HMAC_Final(&ctx,out,&j); out+=j; olen-=j; HMAC_Final(&ctx_tmp,A1,&A1_len); /* calc the next A1 value */ } else /* last one */ { HMAC_Final(&ctx,A1,&A1_len); memcpy(out,A1,olen); break; } } HMAC_cleanup(&ctx); HMAC_cleanup(&ctx_tmp); memset(A1,0,sizeof(A1)); }
static void hmac_finish(struct tc *tc) { struct hmac_priv *hp = crypto_priv(tc); if (!hp) return; HMAC_cleanup(&hp->hp_ctx); free(hp); }
bool HMAC_Validate(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr) { HMAC_CTX ctx; const EVP_MD * pmd = NULL; byte * rgbOut = NULL; unsigned int cbOut; bool f = false; unsigned int i; #ifdef USE_CBOR_CONTEXT cn_cbor_context * context = &pcose->m_message.m_allocContext; #endif HMAC_CTX_init(&ctx); switch (HSize) { case 256: pmd = EVP_sha256(); break; case 384: pmd = EVP_sha384(); break; case 512: pmd = EVP_sha512(); break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break; } rgbOut = COSE_CALLOC(EVP_MAX_MD_SIZE, 1, context); CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(HMAC_Init(&ctx, pbKey, (int) cbKey, pmd), COSE_ERR_CRYPTO_FAIL); CHECK_CONDITION(HMAC_Update(&ctx, pbAuthData, cbAuthData), COSE_ERR_CRYPTO_FAIL); CHECK_CONDITION(HMAC_Final(&ctx, rgbOut, &cbOut), COSE_ERR_CRYPTO_FAIL); cn_cbor * cn = _COSE_arrayget_int(&pcose->m_message, INDEX_MAC_TAG); CHECK_CONDITION(cn != NULL, COSE_ERR_CBOR); if (cn->length > (int) cbOut) return false; for (i = 0; i < (unsigned int) TSize/8; i++) f |= (cn->v.bytes[i] != rgbOut[i]); HMAC_cleanup(&ctx); return !f; errorReturn: COSE_FREE(rgbOut, context); HMAC_cleanup(&ctx); return false; }
static int tls_hash(StringInfo* secret, StringInfo* seed, const EVP_MD *md, StringInfo* out) { uint8_t *ptr; unsigned int left; int tocpy; uint8_t *A; uint8_t _A[48],tmp[48]; unsigned int A_l,tmp_l; HMAC_CTX ctx; ptr = out->data; left = out->data_len; ssl_print_string("tls_hash: hash secret", secret); ssl_print_string("tls_hash: hash seed", seed); A=seed->data; A_l=seed->data_len; while(left){ HMAC_CTX_init(&ctx); HMAC_Init(&ctx, secret->data, secret->data_len, md); HMAC_Update(&ctx,A,A_l); HMAC_Final(&ctx,_A,&A_l); HMAC_cleanup(&ctx); A=_A; HMAC_CTX_init(&ctx); HMAC_Init(&ctx,secret->data,secret->data_len,md); HMAC_Update(&ctx,A,A_l); HMAC_Update(&ctx,seed->data,seed->data_len); HMAC_Final(&ctx,tmp,&tmp_l); HMAC_cleanup(&ctx); tocpy=std::min(left,tmp_l); memcpy(ptr,tmp,tocpy); ptr+=tocpy; left-=tocpy; } ssl_print_string("hash out", out); return (0); }
void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) { HMAC_Final(ctx,hashmacbuf,len); #ifndef OLD_CRYPTO HMAC_CTX_cleanup(ctx); #else HMAC_cleanup(ctx); #endif SAFE_FREE(ctx); }
static void hmac_destroy(struct crypt *c) { struct hmac_priv *hp = crypt_priv(c); if (!hp) return; HMAC_cleanup(&hp->hp_ctx); free(hp); free(c); }
void mac_clear(Mac *mac) { if (mac->type == SSH_UMAC) { if (mac->umac_ctx != NULL) umac_delete(mac->umac_ctx); } else if (mac->evp_md != NULL) HMAC_cleanup(&mac->evp_ctx); mac->evp_md = NULL; mac->umac_ctx = NULL; }
void hmac_final(HMACCTX ctx, unsigned char *hashmacbuf, unsigned int *len) { HMAC_Final(ctx,hashmacbuf,len); #if OPENSSL_VERSION_NUMBER > 0x10100000L HMAC_CTX_free(ctx); ctx = NULL; #else HMAC_cleanup(ctx); SAFE_FREE(ctx); ctx = NULL; #endif }
int main(int argc, char **argv) { Octstr *data, *filename, *mac, *key; unsigned char macbuf[EVP_MAX_MD_SIZE], *p; int mac_len; #ifdef HAVE_LIBSSL HMAC_CTX ctx; #endif gwlib_init(); get_and_set_debugs(argc, argv, NULL); if (argc < 3) panic(0, "Syntax: %s <key> <file>\n", argv[0]); key = octstr_create(argv[1]); filename = octstr_create(argv[2]); data = octstr_read_file(octstr_get_cstr(filename)); if (data == NULL) panic(0, "Cannot read file."); debug("",0,"Dumping file `%s':", octstr_get_cstr(filename)); octstr_dump(data, 0); #ifdef HAVE_LIBSSL HMAC_Init(&ctx, octstr_get_cstr(key), octstr_len(key), EVP_sha1()); p = HMAC(EVP_sha1(), octstr_get_cstr(key), octstr_len(key), octstr_get_cstr(data), octstr_len(data), macbuf, &mac_len); HMAC_cleanup(&ctx); #else macbuf[0] = 0; mac_len = 0; p = macbuf; warning(0, "No SSL support. Can't calculate HMAC value."); #endif mac = octstr_create_from_data(p, mac_len); octstr_binary_to_hex(mac, 0); debug("",0,"HMAC of file `%s' and key `%s' is:", octstr_get_cstr(filename), octstr_get_cstr(key)); octstr_dump(mac, 0); octstr_destroy(data); octstr_destroy(mac); octstr_destroy(key); gwlib_shutdown(); return 0; }
void *por_tag_thread(void *threadargs_ptr){ HMAC_CTX ctx; unsigned char digest[SHA_DIGEST_LENGTH]; unsigned int digest_len = 0; unsigned int block; int *ret = NULL; unsigned char buf[POR_BLOCK_SIZE]; struct thread_arguments *threadargs = threadargs_ptr; int i = 0; if(!threadargs || !threadargs->file || !threadargs->tags || !threadargs->key || !threadargs->numblocks) goto cleanup; /* Allocate memory for return value - this should be freed by the checker */ ret = malloc(sizeof(int)); if(!ret) goto cleanup; *ret = 0; /* For N threads, read in and tag each Nth block */ block = threadargs->threadid; for(i = 0; i < threadargs->numblocks; i++){ memset(digest, 0, SHA_DIGEST_LENGTH); memset(buf, 0, POR_BLOCK_SIZE); fseek(threadargs->file, (block*POR_BLOCK_SIZE), SEEK_SET); fread(buf, POR_BLOCK_SIZE, 1, threadargs->file); if(ferror(threadargs->file)) goto cleanup; /* Calculate the tag for this block */ HMAC_CTX_init(&ctx); HMAC_Init(&ctx, threadargs->key->prf_key, threadargs->key->prf_key_size, EVP_sha1()); HMAC_Update(&ctx, (const unsigned char *)&block, sizeof(unsigned int)); HMAC_Update(&ctx, (unsigned char *)threadargs->filepath, (int)threadargs->filepath_len); HMAC_Update(&ctx, buf, POR_BLOCK_SIZE); HMAC_Final(&ctx, digest, &digest_len); HMAC_cleanup(&ctx); /* Store the tag in a buffer until all threads are done. Writer should destroy tags. */ memcpy((threadargs->tags + (SHA_DIGEST_LENGTH * block)), digest, digest_len); block += NUM_THREADS; } *ret = 1; pthread_exit(ret); cleanup: pthread_exit(ret); }
void HMAC::release(void) { if(context) HMAC_cleanup((HMAC_CTX *)context); if(context) { delete (HMAC_CTX *)context; context = NULL; } bufsize = 0; textbuf[0] = 0; }
bool HMAC_Create(COSE_MacMessage * pcose, int HSize, int TSize, const byte * pbKey, size_t cbKey, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr) { HMAC_CTX ctx; const EVP_MD * pmd = NULL; byte * rgbOut = NULL; unsigned int cbOut; #ifdef USE_CBOR_CONTEXT cn_cbor_context * context = &pcose->m_message.m_allocContext; #endif HMAC_CTX_init(&ctx); if (0) { errorReturn: COSE_FREE(rgbOut, context); HMAC_cleanup(&ctx); return false; } switch (HSize) { case 256: pmd = EVP_sha256(); break; case 384: pmd = EVP_sha384(); break; case 512: pmd = EVP_sha512(); break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break; } rgbOut = COSE_CALLOC(EVP_MAX_MD_SIZE, 1, context); CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY); CHECK_CONDITION(HMAC_Init(&ctx, pbKey, (int) cbKey, pmd), COSE_ERR_CRYPTO_FAIL); CHECK_CONDITION(HMAC_Update(&ctx, pbAuthData, cbAuthData), COSE_ERR_CRYPTO_FAIL); CHECK_CONDITION(HMAC_Final(&ctx, rgbOut, &cbOut), COSE_ERR_CRYPTO_FAIL); CHECK_CONDITION(_COSE_array_replace(&pcose->m_message, cn_cbor_data_create(rgbOut, TSize / 8, CBOR_CONTEXT_PARAM_COMMA NULL), INDEX_MAC_TAG, CBOR_CONTEXT_PARAM_COMMA NULL), COSE_ERR_CBOR); HMAC_cleanup(&ctx); return true; }
void mac_clear(Mac *mac) { #ifdef UMAC_HAS_BEEN_UNBROKEN if (mac->type == SSH_UMAC) { if (mac->umac_ctx != NULL) umac_delete(mac->umac_ctx); } else if (mac->type == SSH_UMAC128) { if (mac->umac_ctx != NULL) umac128_delete(mac->umac_ctx); } else #endif if (mac->evp_md != NULL) HMAC_cleanup(&mac->evp_ctx); mac->evp_md = NULL; mac->umac_ctx = NULL; }
LONGBOW_TEST_CASE(Specialization, test_hmac_sha512) { HMAC_CTX ctx; char key[] = "apple_pie_is_good"; int fd; uint8_t to_digest_buffer[MAXPATHLEN]; ssize_t to_digest_length; uint8_t true_hmac_buffer[MAXPATHLEN]; ssize_t true_hmac_length; LONGBOW_STOP_DEPRECATED_WARNINGS HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key, sizeof(key), EVP_sha512(), NULL); LONGBOW_START_DEPRECATED_WARNINGS fd = open("test_random_bytes", O_RDONLY); assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); to_digest_length = read(fd, to_digest_buffer, sizeof(to_digest_buffer)); assertTrue(to_digest_length > 0, "Could not read input file: %s", strerror(errno)); close(fd); fd = open("test_random_bytes.hmac_sha512", O_RDONLY); assertTrue(fd > 0, "Could not open input file: %s", strerror(errno)); true_hmac_length = read(fd, true_hmac_buffer, sizeof(true_hmac_buffer)); assertTrue(true_hmac_length > 0, "Could not read input file: %s", strerror(errno)); close(fd); _hmacInit(&ctx); _hmacUpdate(&ctx, to_digest_buffer, to_digest_length); PARCBuffer *output = _hmacFinalize(&ctx); assertTrue(parcBuffer_Position(output) == true_hmac_length, "hmac wrong length, expected %zu got %zu", true_hmac_length, parcBuffer_Position(output)); assertTrue(memcmp(parcByteArray_Array(parcBuffer_Array(output)), true_hmac_buffer, true_hmac_length) == 0, "hmac values did not match"); LONGBOW_STOP_DEPRECATED_WARNINGS HMAC_cleanup(&ctx); LONGBOW_START_DEPRECATED_WARNINGS parcBuffer_Release(&output); }
static void dohmac(void) { HMAC_CTX ctx; unsigned char hmac_value[EVP_MAX_MD_SIZE]; unsigned int hmac_len, i; char key[16] = "etaonrishdlcupfm"; unsigned char buf[256]; /* Generate digest of input stream */ HMAC_Init(&ctx, key, sizeof(key), EVP_sha1()); memcpy(buf, "abcdefghijklmnopqrstuvwxyz", 26); HMAC_Update(&ctx, buf, 26); HMAC_Final(&ctx, hmac_value, &hmac_len); HMAC_cleanup(&ctx); for(i = 0; i < hmac_len; i++) fprintf(stderr, "%02x", hmac_value[i]); fprintf(stderr, "\n"); return; }
u_char * mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen) { HMAC_CTX c; static u_char m[EVP_MAX_MD_SIZE]; u_char b[4]; if (mac->key == NULL) fatal("mac_compute: no key"); if (mac->mac_len > sizeof(m)) fatal("mac_compute: mac too long"); HMAC_Init(&c, mac->key, mac->key_len, mac->md); PUT_32BIT(b, seqno); HMAC_Update(&c, b, sizeof(b)); HMAC_Update(&c, data, datalen); HMAC_Final(&c, m, NULL); HMAC_cleanup(&c); return (m); }
static void switch_write_mac(void) { /* First we can clear the write MAC, kept from rekeying. */ if (write_macs[write_mac_idx].key) { clear_mac(&(write_macs[write_mac_idx])); #if OPENSSL_VERSION_NUMBER > 0x000907000L HMAC_CTX_cleanup(&(write_ctxs[write_mac_idx])); #else HMAC_cleanup(&(write_ctxs[write_mac_idx])); #endif /* Now we can switch the index. */ if (write_mac_idx == 1) { write_mac_idx = 0; return; } write_mac_idx = 1; } }
/* {{{ libssh2_mac_method_hmac_sha1_hash * Calculate hash using full sha1 value */ static int libssh2_mac_method_hmac_sha1_hash(LIBSSH2_SESSION *session, unsigned char *buf, unsigned long seqno, const unsigned char *packet, unsigned long packet_len, const unsigned char *addtl, unsigned long addtl_len, void **abstract) { HMAC_CTX ctx; unsigned char seqno_buf[4]; libssh2_htonu32(seqno_buf, seqno); HMAC_Init(&ctx, *abstract, 20, EVP_sha1()); HMAC_Update(&ctx, seqno_buf, 4); HMAC_Update(&ctx, packet, packet_len); if (addtl && addtl_len) { HMAC_Update(&ctx, addtl, addtl_len); } HMAC_Final(&ctx, buf, NULL); HMAC_cleanup(&ctx); return 0; }
static void switch_read_mac(void) { /* First we can clear the read MAC, kept from rekeying. */ if (read_macs[read_mac_idx].key) { clear_mac(&(read_macs[read_mac_idx])); #if OPENSSL_VERSION_NUMBER > 0x000907000L HMAC_CTX_cleanup(&(read_ctxs[read_mac_idx])); #else HMAC_cleanup(&(read_ctxs[read_mac_idx])); #endif mac_blockszs[read_mac_idx] = 0; /* Now we can switch the index. */ if (read_mac_idx == 1) { read_mac_idx = 0; return; } read_mac_idx = 1; } }
unsigned char *HMAC(//fixed to SHA256: EVP_MD *evp_md, unsigned char *key, int key_len, unsigned char *d, int n, unsigned char *md) //always 32, unsigned int *md_len) { HMAC_CTX c; //static unsigned char m[EVP_MAX_MD_SIZE]; static unsigned char m[SHA256_DIGEST_LENGTH]; if (md == NULL) md=m; //HMAC_Init(&c,key,key_len,evp_md); HMAC_Init(&c, key, key_len); HMAC_Update(&c,d,n); HMAC_Final(&c,md); //always 32:,md_len); HMAC_cleanup(&c); return(md); }
int por_verify_block(char *filepath, size_t filepath_len, unsigned char *block, size_t block_len, unsigned int index, unsigned char *tag, size_t tag_len){ HMAC_CTX ctx; POR_key *key = NULL; unsigned char digest[SHA_DIGEST_LENGTH]; unsigned int digest_len = 0; int ret = 0; if(!filepath || !block || !block_len || !tag || !tag_len) return 0; if(filepath_len >= MAXPATHLEN) return 0; key = por_get_keys(); if(!key) goto cleanup; HMAC_CTX_init(&ctx); HMAC_Init(&ctx, key->prf_key, key->prf_key_size, EVP_sha1()); HMAC_Update(&ctx, (const unsigned char *)&index, sizeof(unsigned int)); HMAC_Update(&ctx, (unsigned char *)filepath, (int)filepath_len); HMAC_Update(&ctx, block, block_len); HMAC_Final(&ctx, digest, &digest_len); HMAC_cleanup(&ctx); ret = memcmp(digest, tag, tag_len); /* printf("Tag: "); printhex(tag, tag_len); printf("Verify: "); printhex(digest, digest_len); */ if(key) destroy_por_key(key); if(ret == 0) return 1; cleanup: return 0; }
int P_hash(const char *digest, unsigned char *dest, int dlen, unsigned char *secret, int sslen, unsigned char *seed, int slen) { unsigned char hmac[20]; uint32_t hlen; HMAC_CTX hm; const EVP_MD *md = EVP_get_digestbyname(digest); uint32_t tmpslen; unsigned char tmpseed[slen]; unsigned char *out = dest; int pending = dlen; // Copy initial seed memcpy(tmpseed, seed, slen); tmpslen = slen; // Calculate enough data to fill destination while (pending > 0) { HMAC_Init(&hm, secret, sslen, md); HMAC_Update(&hm, tmpseed, tmpslen); HMAC_Final(&hm, tmpseed, &tmpslen); HMAC_Init(&hm, secret, sslen, md); HMAC_Update(&hm, tmpseed, tmpslen); HMAC_Update(&hm, seed, slen); HMAC_Final(&hm, hmac, &hlen); hlen = (hlen > pending) ? pending : hlen; memcpy(out, hmac, hlen); out += hlen; pending -= hlen; } HMAC_cleanup(&hm); return hlen; }
char * host_hash(const char *host, const char *name_from_hostfile, u_int src_len) { const EVP_MD *md = EVP_sha1(); HMAC_CTX mac_ctx; u_char salt[256], result[256]; char uu_salt[512], uu_result[512]; static char encoded[1024]; u_int i, len; len = EVP_MD_size(md); if (name_from_hostfile == NULL) { /* Create new salt */ for (i = 0; i < len; i++) salt[i] = arc4random(); } else { /* Extract salt from known host entry */ if (extract_salt(name_from_hostfile, src_len, salt, sizeof(salt)) == -1) return (NULL); } HMAC_Init(&mac_ctx, salt, len, md); HMAC_Update(&mac_ctx, __UNCONST(host), strlen(host)); HMAC_Final(&mac_ctx, result, NULL); HMAC_cleanup(&mac_ctx); if (__b64_ntop(salt, len, uu_salt, sizeof(uu_salt)) == -1 || __b64_ntop(result, len, uu_result, sizeof(uu_result)) == -1) fatal("host_hash: __b64_ntop failed"); snprintf(encoded, sizeof(encoded), "%s%s%c%s", HASH_MAGIC, uu_salt, HASH_DELIM, uu_result); return (encoded); }
unsigned char *HMAC2(//fixed to SHA256: EVP_MD *evp_md, unsigned char *key, int key_len, unsigned char *d, int n, unsigned char *md) //always 64, unsigned int *md_len) { HMAC_CTX c; //static unsigned char m[EVP_MAX_MD_SIZE]; static unsigned char m[2*SHA256_DIGEST_LENGTH]; if (md == NULL) md=m; //first round HMAC_Init(&c, key, key_len); HMAC_Update(&c,d,n); HMAC_Final(&c,md); //second round HMAC_Init(&c, NULL, key_len); //only performs memcpy HMAC_Update(&c,d,n); HMAC_Final(&c,md+SHA256_DIGEST_LENGTH); HMAC_cleanup(&c); return(md); }
int por_tag_file(char *filepath, size_t filepath_len, char *tagfilepath, size_t tagfilepath_len){ POR_key *key = NULL; FILE *file = NULL; FILE *tagfile = NULL; char realtagfilepath[MAXPATHLEN]; char yesorno = 0; unsigned int index = 0; #ifdef THREADING pthread_t threads[NUM_THREADS]; int *thread_return = NULL; struct thread_arguments threadargs[NUM_THREADS]; struct stat st; size_t numfileblocks = 0; unsigned char *tags = NULL; unsigned int digest_len = 0; memset(threads, 0, sizeof(pthread_t) * NUM_THREADS); memset(&st, 0, sizeof(struct stat)); #else HMAC_CTX ctx; unsigned char buf[POR_BLOCK_SIZE]; unsigned char digest[SHA_DIGEST_LENGTH]; unsigned int digest_len = 0; #endif memset(realtagfilepath, 0, MAXPATHLEN); if(!filepath) return 0; if(filepath_len >= MAXPATHLEN) return 0; if(tagfilepath_len >= MAXPATHLEN) return 0; /* If no tag file path is specified, add a .tag extension to the filepath */ if(!tagfilepath && (filepath_len < MAXPATHLEN - 5)){ if( snprintf(realtagfilepath, MAXPATHLEN, "%s.tag", filepath) >= MAXPATHLEN ) goto cleanup; }else{ memcpy(realtagfilepath, tagfilepath, tagfilepath_len); } /* Check to see if the tag file exists */ if( (access(realtagfilepath, F_OK) == 0)){ fprintf(stdout, "WARNING: A tag file for %s already exist; do you want to overwite (y/N)?", filepath); scanf("%c", &yesorno); if(yesorno != 'y') goto exit; } tagfile = fopen(realtagfilepath, "w"); if(!tagfile){ fprintf(stderr, "ERROR: Was not able to create %s.\n", realtagfilepath); goto cleanup; } /* Get the POR key */ key = por_get_keys(); if(!key) goto cleanup; OpenSSL_add_all_digests(); #ifdef THREADING /* Calculate the number blocks in the file */ if(stat(filepath, &st) < 0) return 0; numfileblocks = (st.st_size/POR_BLOCK_SIZE); if(st.st_size%POR_BLOCK_SIZE) numfileblocks++; /* Allocate buffer to hold tags until we write them out */ if( ((tags = malloc( SHA_DIGEST_LENGTH * numfileblocks )) == NULL)) goto cleanup; memset(tags, 0, (SHA_DIGEST_LENGTH * numfileblocks)); for(index = 0; index < NUM_THREADS; index++){ /* Open a unique file descriptor for each thread to avoid race conditions */ threadargs[index].file = fopen(filepath, "r"); if(!threadargs[index].file) goto cleanup; threadargs[index].filepath = filepath; threadargs[index].filepath_len = filepath_len; threadargs[index].key = key; threadargs[index].threadid = index; threadargs[index].numblocks = numfileblocks/NUM_THREADS; threadargs[index].tags = tags; /* If there is not an equal number of blocks to tag, add the extra blocks to * the corresponding threads */ if(index < numfileblocks%NUM_THREADS) threadargs[index].numblocks++; /* If the thread has blocks to tag, spawn it */ if(threadargs[index].numblocks > 0) if(pthread_create(&threads[index], NULL, por_tag_thread, (void *) &threadargs[index]) != 0) goto cleanup; } /* Check to see all tags were generated */ for(index = 0; index < NUM_THREADS; index++){ if(threads[index]){ if(pthread_join(threads[index], (void **)&thread_return) != 0) goto cleanup; if(!thread_return || !(*thread_return))goto cleanup; else free(thread_return); /* Close the file */ if(threadargs[index].file) fclose(threadargs[index].file); } } /* Write the tags out */ for(index = 0; index < numfileblocks; index++){ if(!tags[index]) goto cleanup; /* Write the tag to disk */ digest_len = SHA_DIGEST_LENGTH; fwrite(&digest_len, sizeof(unsigned int), 1, tagfile); if(ferror(tagfile)) goto cleanup; fwrite(tags + (SHA_DIGEST_LENGTH * index), SHA_DIGEST_LENGTH, 1, tagfile); if(ferror(tagfile)) goto cleanup; } sfree(tags, (SHA_DIGEST_LENGTH * numfileblocks)); #else /* Open the file for reading */ file = fopen(filepath, "r"); if(!file){ fprintf(stderr, "ERROR: Was not able to open %s for reading.\n", filepath); goto cleanup; } index = 0; do{ /* Calculate the tag for this block */ HMAC_CTX_init(&ctx); HMAC_Init(&ctx, key->prf_key, key->prf_key_size, EVP_sha1()); memset(buf, 0, POR_BLOCK_SIZE); fread(buf, POR_BLOCK_SIZE, 1, file); if(ferror(file)) goto cleanup; HMAC_Update(&ctx, (const unsigned char *)&index, sizeof(unsigned int)); HMAC_Update(&ctx, (unsigned char *)filepath, (int)filepath_len); HMAC_Update(&ctx, buf, POR_BLOCK_SIZE); HMAC_Final(&ctx, digest, &digest_len); /* Write the tag to disk */ fwrite(&digest_len, sizeof(unsigned int), 1, tagfile); if(ferror(tagfile)) goto cleanup; fwrite(digest, digest_len, 1, tagfile); if(ferror(tagfile)) goto cleanup; index++; HMAC_cleanup(&ctx); }while(!feof(file)); #endif exit: destroy_por_key(key); if(file) fclose(file); if(tagfile) fclose(tagfile); return 1; cleanup: fprintf(stderr, "ERROR: Was unable to create tag file.\n"); #ifdef THREADING for(index = 0; index < NUM_THREADS; index++){ if(threads[index] != NULL) pthread_cancel(threads[index]); if(threadargs[index].file) fclose(threadargs[index].file); } sfree(tags, (SHA_DIGEST_LENGTH * numfileblocks)); #endif if(key) destroy_por_key(key); if(file) fclose(file); if(tagfile){ ftruncate(fileno(tagfile), 0); unlink(realtagfilepath); fclose(tagfile); } return 0; }
USES_APPLE_DEPRECATED_API /* OpenSSL API has been deprecated by Apple */ /* avoid inclusion of these FR headers which conflict w/ OpenSSL */ #define _FR_MD4_H #define _FR_SHA1_H #include "extern.h" #include <string.h> #include <openssl/des.h> /* des_cblock */ #include <openssl/md5.h> #include <openssl/hmac.h> /* * Generate the State attribute, suitable for passing to fr_pair_make(). * 'challenge' must be a null terminated string, and be sized at least * as large as indicated in the function definition. * * Returns 0 on success, non-zero otherwise. For successful returns, * 'rad_state' (suitable for passing to fr_pair_make()) and 'raw_state', * if non-NULL, will be filled in. * * In the simplest implementation, we would just use the challenge as state. * Unfortunately, the RADIUS secret protects only the User-Password * attribute; an attacker that can remove packets from the wire and insert * new ones can simply insert a replayed state without having to know * the secret. If not for an attacker that can remove packets from the * network, I believe trivial state to be secure. * * So, we have to make up for that deficiency by signing our state with * data unique to this specific request. A NAS would use the Request * Authenticator, but we don't know what that will be when the State is * returned to us, so we'll use the time. So our replay prevention * is limited to a time interval (inst->challenge_delay). We could keep * track of all challenges issued over that time interval for * better protection. * * Our state, then, is * (challenge + flags + time + hmac(challenge + resync + time, key)), * where '+' denotes concatentation, 'challenge' is ... the challenge, * 'flags' is a 32-bit value that can be used to record additional info, * 'time' is the 32-bit time (LSB if time_t is 64 bits), and 'key' is a * random key, generated in mod_instantiate(). 'flags' and 'time' are * in network byte order. * * As the signing key is unique to each server, only the server which * generates a challenge can verify it; this should be OK if your NAS's * load balance across RADIUS servers using a "first available" algorithm. * If your NAS's round-robin and don't "stick" to the same server if they * see a State attribute (ugh), you could use the RADIUS secret instead, * but read RFC 2104 first, and make very sure you really want to do this. * * Since only the "same server" can verify State, 'flags' and 'time' doesn't * really need to be in network byte order, but we do it anyway. * * The State attribute is an octet string, however some versions of Cisco * IOS and Catalyst OS (at least IOS 12.1(26)E4 and CatOS 7.6.12) treat it * as an ASCII string (they only return data up to the first NUL byte). * So we must handle state as an ASCII string (0x00 -> 0x3030). */ /* * OTP_MAX_RADSTATE_LEN is composed of: * * clen * 2 + challenge * 8 + flags * 8 + time * sizeof(hmac) * 2 + hmac * 1 \0' */ /** Generate an OTP state value * * Generates an OTP state value (an string of ASCII hexits in an opaque binary * string). * * @param[out] state buffer in which to write the generated state value. * @param[in] challenge The challenge value. * @param[in] clen The length of the challenge data. * @param[in] flags to remember. * @param[in] when the challenge was originally generated. * @param[in] key HMAC key. * @return the amount of data written into the state buffer. */ size_t otp_gen_state(char state[OTP_MAX_RADSTATE_LEN], char const challenge[OTP_MAX_CHALLENGE_LEN], size_t clen, int32_t flags, int32_t when, uint8_t const key[16]) { HMAC_CTX hmac_ctx; uint8_t hmac[MD5_DIGEST_LENGTH]; char *p; /* * Generate the hmac. We already have a dependency on openssl for * DES, so we'll use it's hmac functionality also -- saves us from * having to collect the data to be signed into one * contiguous piece. */ HMAC_Init(&hmac_ctx, key, sizeof(key[0]) * 16, EVP_md5()); HMAC_Update(&hmac_ctx, (uint8_t const *) challenge, clen); HMAC_Update(&hmac_ctx, (uint8_t *) &flags, 4); HMAC_Update(&hmac_ctx, (uint8_t *) &when, 4); HMAC_Final(&hmac_ctx, hmac, NULL); HMAC_cleanup(&hmac_ctx); /* * Generate the state. */ p = state; /* * Add the challenge (which is already ASCII encoded) */ p += fr_bin2hex(p, (uint8_t const *) challenge, clen); /* Add the flags and time. */ p += fr_bin2hex(p, (uint8_t *) &flags, 4); p += fr_bin2hex(p, (uint8_t *) &when, 4); /* Add the hmac. */ p += fr_bin2hex(p, hmac, 16); return p - state; }