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; }
int cipher_write_tag( cipher_context_t *ctx, unsigned char *tag, size_t tag_len ) { if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); if( POLARSSL_ENCRYPT != ctx->operation ) return( POLARSSL_ERR_CIPHER_BAD_INPUT_DATA ); if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) return gcm_finish( (gcm_context *) ctx->cipher_ctx, tag, tag_len ); return( 0 ); }
int cipher_check_tag( cipher_context_t *ctx, const unsigned char *tag, size_t tag_len ) { int ret; if( NULL == ctx || NULL == ctx->cipher_info || POLARSSL_DECRYPT != ctx->operation ) { return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; } #if defined(POLARSSL_GCM_C) if( POLARSSL_MODE_GCM == ctx->cipher_info->mode ) { unsigned char check_tag[16]; size_t i; int diff; if( tag_len > sizeof( check_tag ) ) return POLARSSL_ERR_CIPHER_BAD_INPUT_DATA; if( 0 != ( ret = gcm_finish( (gcm_context *) ctx->cipher_ctx, check_tag, tag_len ) ) ) { return( ret ); } /* Check the tag in "constant-time" */ for( diff = 0, i = 0; i < tag_len; i++ ) diff |= tag[i] ^ check_tag[i]; if( diff != 0 ) return( POLARSSL_ERR_CIPHER_AUTH_FAILED ); return( 0 ); } #endif return( 0 ); }
/*! \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); }