void gcm_init(gcm* g,int nk,char *key,int niv,char *iv) { /* iv size niv is usually 12 bytes (96 bits). AES key size nk can be 16,24 or 32 bytes */ int i; MR_BYTE H[16]; for (i=0;i<16;i++) {H[i]=0; g->stateX[i]=0;} aes_init(&(g->a),MR_ECB,nk,key,iv); aes_ecb_encrypt(&(g->a),H); /* E(K,0) */ precompute(g,H); g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0; if (niv==12) { for (i=0;i<12;i++) g->a.f[i]=iv[i]; unpack((MR_WORD)1,(MR_BYTE *)&(g->a.f[12])); /* initialise IV */ for (i=0;i<16;i++) g->Y_0[i]=g->a.f[i]; } else { g->status=GCM_ACCEPTING_CIPHER; gcm_add_cipher(g,0,iv,niv,NULL); /* GHASH(H,0,IV) */ gcm_wrap(g); for (i=0;i<16;i++) {g->a.f[i]=g->stateX[i];g->Y_0[i]=g->a.f[i];g->stateX[i]=0;} g->lenA[0]=g->lenC[0]=g->lenA[1]=g->lenC[1]=0; } g->status=GCM_ACCEPTING_HEADER; }
void AES_GCM_DECRYPT(octet *K,octet *IV,octet *H,octet *C,octet *P,octet *T) { gcm g; gcm_init(&g,K->len,K->val,IV->len,IV->val); gcm_add_header(&g,H->val,H->len); gcm_add_cipher(&g,GCM_DECRYPTING,P->val,C->len,C->val); P->len=C->len; gcm_finish(&g,T->val); T->len=16; }
/*! \brief Decrypt data using AES GCM * * AES is run as a block cypher in the GCM mode of operation. The key size is 128 bits. * This function will decrypt any data length. * * @param key 128 bit secret key * @param IV 96 bit initialization vector * @param header Additional authenticated data (AAD). This data is authenticated, but not decrypted. * @param ciphertext Encrypted data. * @return plaintext Decrypted data. It is the same length as the ciphertext. * @return tag 128 bit authentication tag. * @return rtn Returns 0 if successful or else an error code */ AESGCM_EXPORT int aesGcmDecrypt(char* key, char* IV, char* header, int headerLength, char* ciphertext, int ciphertextLength, char* plaintext, char* tag) { gcm g; int keyLength=AS; int tagLength=AS; gcm_init(&g,keyLength,key,IVLength,IV); if(!gcm_add_header(&g,header,headerLength)) { return AES_INIT_ERROR; } if(!gcm_add_cipher(&g,GCM_DECRYPTING,plaintext,ciphertextLength,ciphertext)) { return AES_DECRYPT_ERROR; } gcm_finish(&g,tag); tagLength=16; return 0; }
PlaintextMessage EncryptedMessage::decrypt(const G2& P, const G2& Ppub, G1 D, PFC *pfc) { G2 uCalc; G2 U = (*autData).getU(); Big ud_hash = (*pfc).hash_to_aes_key((*pfc).pairing(U,D)); Big ses_key; Big r; int nbOfRecipients = (*autData).getNbOfRecipients(); Big W; Big V = (*autData).getV(); Big rho, rho_hash; vector <Big> ws = (*autData).getEncryptedRecipientKeys(); char P_text[Clen]; bool integrity = false; time_t begin_time = clock(); int i = 0; while(U != uCalc && i < nbOfRecipients){ // rho = V XOR Hash(e(D,U)) W=ws.at(i); rho = lxor(W, ud_hash); // M = W XOR Hash(rho) (*pfc).start_hash(); (*pfc).add_to_hash(rho); rho_hash = (*pfc).finish_hash_to_group(); ses_key = lxor(V, rho_hash); // r = Hash(rho,M) (*pfc).start_hash(); (*pfc).add_to_hash(rho); (*pfc).add_to_hash(ses_key); r = (*pfc).finish_hash_to_group(); uCalc = (*pfc).mult(P,r); i++; } cout << "ses_key is " << endl << ses_key << endl; /************************************************* * AES GCM part of the decryption step * **************************************************/ to_binary(ses_key, HASH_LEN, sessionKey, TRUE); char k1[HASH_LEN/2]; char iv[HASH_LEN/2]; char Tdec[TAG_LEN]; memset(P_text, 0, Clen+1); getIV(iv); getK1(k1); int Alen = (*autData).getLength(); char A[Alen]; (*autData).encodeTo(A); gcm g; gcm_init(&g, HASH_LEN/2, k1, HASH_LEN/2, iv); gcm_add_header(&g, A, Alen); gcm_add_cipher(&g, GCM_DECRYPTING, P_text, Clen, C); gcm_finish(&g, Tdec); integrity = true; for (int j = 0; j < TAG_LEN; j++) { if(Tdec[j] != T[j]) { integrity = false; } } if(integrity == false) { cout << "Received tag T does not correspond to decrypted T. There are some integrity issues here." << endl; } else { cout << "Successful integrity check!" << endl; } message = (string)P_text; return PlaintextMessage(message); }