int eax_done( unsigned char tag[], unsigned long tag_len, eax_state eax[1] ) { int err = EXIT_FAILURE; unsigned char *headermac, *ctmac; unsigned long x, len; if( ( headermac = malloc( AES_BLOCK_SIZE ) ) == NULL ) goto exit3; if( ( ctmac = malloc( AES_BLOCK_SIZE ) ) == NULL ) goto exit2; len = AES_BLOCK_SIZE; if( (err = omac_done( ctmac, &len, eax->ctx_omac )) != EXIT_SUCCESS ) goto exit1; if( (err = omac_done( headermac, &len, eax->hdr_omac )) != EXIT_SUCCESS ) goto exit1; if( (err = ctr_done( eax->ctr )) != 0 ) goto exit1; for( x = 0; x < len && x < tag_len; x++ ) tag[x] = eax->nv[x] ^ headermac[x] ^ ctmac[x]; err = EXIT_SUCCESS; exit1: free( ctmac ); exit2: free( headermac ); exit3: return err; }
/** OMAC multiple blocks of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @param in The data to send through OMAC @param inlen The length of the data to send through OMAC (octets) @param ... tuples of (data,len) pairs to OMAC, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ int omac_memory_multi(int cipher, const unsigned char *key, unsigned long keylen, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { int err; omac_state *omac; va_list args; const unsigned char *curptr; unsigned long curlen; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* allocate ram for omac state */ omac = XMALLOC(sizeof(omac_state)); if (omac == NULL) { return CRYPT_MEM; } /* omac process the message */ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } va_start(args, inlen); curptr = in; curlen = inlen; for (;;) { /* process buf */ if ((err = omac_process(omac, curptr, curlen)) != CRYPT_OK) { goto LBL_ERR; } /* step to next */ curptr = va_arg(args, const unsigned char*); if (curptr == NULL) { break; } curlen = va_arg(args, unsigned long); } if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(omac, sizeof(omac_state)); #endif XFREE(omac); va_end(args); return err; }
/** LTC_OMAC a block of memory @param cipher The index of the desired cipher @param key The secret key @param keylen The length of the secret key (octets) @param in The data to send through LTC_OMAC @param inlen The length of the data to send through LTC_OMAC (octets) @param out [out] The destination of the authentication tag @param outlen [in/out] The max size and resulting size of the authentication tag (octets) @return CRYPT_OK if successful */ int omac_memory(int cipher, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { int err; omac_state *omac; LTC_ARGCHK(key != NULL); LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* is the cipher valid? */ if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { return err; } /* Use accelerator if found */ if (cipher_descriptor[cipher].omac_memory != NULL) { return cipher_descriptor[cipher].omac_memory(key, keylen, in, inlen, out, outlen); } /* allocate ram for omac state */ omac = XMALLOC(sizeof(omac_state)); if (omac == NULL) { return CRYPT_MEM; } /* omac process the message */ if ((err = omac_init(omac, cipher, key, keylen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = omac_process(omac, in, inlen)) != CRYPT_OK) { goto LBL_ERR; } if ((err = omac_done(omac, out, outlen)) != CRYPT_OK) { goto LBL_ERR; } err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(omac, sizeof(omac_state)); #endif XFREE(omac); return err; }
/** LTC_OMAC a file @param cipher The index of the cipher desired @param key The secret key @param keylen The length of the secret key (octets) @param filename The name of the file you wish to LTC_OMAC @param out [out] Where the authentication tag is to be stored @param outlen [in/out] The max size and resulting size of the authentication tag @return CRYPT_OK if successful, CRYPT_NOP if file support has been disabled */ int omac_file(int cipher, const unsigned char *key, unsigned long keylen, const char *filename, unsigned char *out, unsigned long *outlen) { #ifdef LTC_NO_FILE return CRYPT_NOP; #else int err, x; omac_state omac; FILE *in; unsigned char buf[512]; LTC_ARGCHK(key != NULL); LTC_ARGCHK(filename != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); in = fopen(filename, "rb"); if (in == NULL) { return CRYPT_FILE_NOTFOUND; } if ((err = omac_init(&omac, cipher, key, keylen)) != CRYPT_OK) { fclose(in); return err; } do { x = fread(buf, 1, sizeof(buf), in); if ((err = omac_process(&omac, buf, x)) != CRYPT_OK) { fclose(in); return err; } } while (x == sizeof(buf)); fclose(in); if ((err = omac_done(&omac, out, outlen)) != CRYPT_OK) { return err; } #ifdef LTC_CLEAN_STACK zeromem(buf, sizeof(buf)); #endif return CRYPT_OK; #endif }
/** Terminate an EAX session and get the tag. @param eax The EAX state @param tag [out] The destination of the authentication tag @param taglen [in/out] The max length and resulting length of the authentication tag @return CRYPT_OK if successful */ int eax_done(eax_state *eax, unsigned char *tag, unsigned long *taglen) { int err; unsigned char *headermac, *ctmac; unsigned long x, len; LTC_ARGCHK(eax != NULL); LTC_ARGCHK(tag != NULL); LTC_ARGCHK(taglen != NULL); /* allocate ram */ headermac = XMALLOC(MAXBLOCKSIZE); ctmac = XMALLOC(MAXBLOCKSIZE); if (headermac == NULL || ctmac == NULL) { if (headermac != NULL) { XFREE(headermac); } if (ctmac != NULL) { XFREE(ctmac); } return CRYPT_MEM; } /* finish ctomac */ len = MAXBLOCKSIZE; if ((err = omac_done(&eax->ctomac, ctmac, &len)) != CRYPT_OK) { goto LBL_ERR; } /* finish headeromac */ /* note we specifically don't reset len so the two lens are minimal */ if ((err = omac_done(&eax->headeromac, headermac, &len)) != CRYPT_OK) { goto LBL_ERR; } /* terminate the CTR chain */ if ((err = ctr_done(&eax->ctr)) != CRYPT_OK) { goto LBL_ERR; } /* compute N xor H xor C */ for (x = 0; x < len && x < *taglen; x++) { tag[x] = eax->N[x] ^ headermac[x] ^ ctmac[x]; } *taglen = x; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(ctmac, MAXBLOCKSIZE); zeromem(headermac, MAXBLOCKSIZE); zeromem(eax, sizeof(*eax)); #endif XFREE(ctmac); XFREE(headermac); return err; }
int eax_init( const unsigned char key[], unsigned long key_len, const unsigned char nonce[], unsigned long nonce_len, const unsigned char hdr[], unsigned long header_len, eax_state eax[1] ) { unsigned char *buf; int err = EXIT_FAILURE; omac_state *omac; unsigned long len; if( header_len > 0 && hdr == NULL ) goto exit3; if( ( buf = malloc( AES_BLOCK_SIZE ) ) == NULL ) goto exit3; if( ( omac = malloc( sizeof(*omac) ) ) == NULL ) goto exit2; memset( buf, 0, AES_BLOCK_SIZE ); if( (err = omac_init(key, key_len, omac)) != EXIT_SUCCESS ) goto exit1; if( (err = omac_process(buf, AES_BLOCK_SIZE, omac)) != EXIT_SUCCESS ) goto exit1; if( (err = omac_process(nonce, nonce_len, omac)) != EXIT_SUCCESS ) goto exit1; len = sizeof( eax->nv ); if( (err = omac_done(eax->nv, &len, omac)) != EXIT_SUCCESS ) goto exit1; memset( buf, 0, AES_BLOCK_SIZE ); buf[AES_BLOCK_SIZE - 1] = 1; if( (err = omac_init(key, key_len, eax->hdr_omac)) != EXIT_SUCCESS ) goto exit1; if( (err = omac_process(buf, AES_BLOCK_SIZE, eax->hdr_omac)) != EXIT_SUCCESS ) goto exit1; if( header_len != 0 && ( (err = omac_process(hdr, header_len, eax->hdr_omac) ) != EXIT_SUCCESS ) ) goto exit1; if( (err = ctr_start(eax->nv, key, key_len, 0, CTR_COUNTER_BIG_ENDIAN, eax->ctr) ) != EXIT_SUCCESS ) goto exit1; if( (err = omac_init(key, key_len, eax->ctx_omac)) != EXIT_SUCCESS ) goto exit1; memset( buf, 0, AES_BLOCK_SIZE ); buf[AES_BLOCK_SIZE - 1] = 2; if( (err = omac_process(buf, AES_BLOCK_SIZE, eax->ctx_omac)) != EXIT_SUCCESS ) goto exit1; err = EXIT_SUCCESS; exit1: free( omac ); exit2: free( buf ); exit3: return err; }