static void aes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count) { AES_cfb128_encrypt(in, out, (unsigned)count, crypt->encrypt_key, crypt->iv, &crypt->num, AES_DECRYPT); }
byte_vector_ptr Processor_AES_CFB128::ProcessData(const byte* p_data, std::size_t size) { auto p_vec = std::make_shared<byte_vector>(size); AES_cfb128_encrypt(p_data, p_vec->data(), size, &key_, ivec_.data(), &num_, type_); return p_vec; }
/*-----------------------------------------------------------------------------------*/ static s8t aes_process(u8t* key, u8t* iv, u8t* input, u8t* output, u16t len, u8t mode) { AES_KEY aes_key; s32t new_ivlen = 0; AES_set_encrypt_key(key, &aes_key); AES_cfb128_encrypt(input, output, len, &aes_key, iv, &new_ivlen, mode); return 0; }
int main(int argc, char *argv[]) { int bytes_read, bytes_written; unsigned char indata[AES_BLOCK_SIZE]; unsigned char outdata[AES_BLOCK_SIZE]; char infile[1024], *outfile, *tmp; /* ckey and ivec are the two 128-bits keys necesary to en- and recrypt your data. Note that ckey can be 192 or 256 bits as well */ unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; if (argc <= 1) { printf("%s will atleast take one argument: the file to be encrypted\n", argv[0]); exit(1); } snprintf(infile, 1023, "%s", argv[1]); FILE *ifp = fopen(infile, "r"); if (ifp == NULL) { fprintf(stderr, "Error: opening file %s to read\n", infile); exit(1); } tmp = basename(infile); outfile = malloc(strlen(tmp) + 5); snprintf(outfile, 1023, "%s.enc", tmp); FILE *ofp = fopen(outfile, "w"); if (ofp == NULL) { fprintf(stderr, "Error: opening %s to write\n", outfile); exit(1); } /* data structure that contains the key itself */ AES_KEY key; /* set the encryption key */ AES_set_encrypt_key(ckey, 128, &key); int num = 16; while (1) { bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp); AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num, AES_ENCRYPT); bytes_written = fwrite(outdata, 1, bytes_read, ofp); if (bytes_read < AES_BLOCK_SIZE) break; } fclose(ifp); fclose(ofp); }
int main(){ char plaintext[] = "Hi I am an AES CFB test vector distributed on 4 128-bit blocks!"; unsigned char key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; unsigned char iv[AES_BLOCK_SIZE] = {0x01, 0xff, 0x83, 0xf2, 0xf9, 0x98, 0xba, 0xa4, 0xda, 0xdc, 0xaa, 0xcc, 0x8e, 0x17, 0xa4, 0x1b}; unsigned char iv_tmp[AES_BLOCK_SIZE]; unsigned char ciphertext[sizeof(plaintext)]; unsigned char deciphertext[sizeof(plaintext)]; AES_KEY ekey; int num = 0; printf("Plaintext: \"%s\"\n", plaintext); printf("IV: "); fprintBuffer_raw(stdout, (char*)iv, sizeof(iv)); printf("\nKey 128: "); fprintBuffer_raw(stdout, (char*)key, sizeof(key)); if (AES_set_encrypt_key(key, 128, &ekey)){ printf("ERROR: in %s, unable to setup AES encryption key\n", __func__); return EXIT_FAILURE; } memcpy(iv_tmp, iv, AES_BLOCK_SIZE); AES_cfb128_encrypt((unsigned char*)plaintext, ciphertext, sizeof(plaintext), &ekey, iv_tmp, &num, AES_ENCRYPT); memcpy(iv_tmp, iv, AES_BLOCK_SIZE); AES_cfb128_encrypt(ciphertext, deciphertext, sizeof(ciphertext), &ekey, iv_tmp, &num, AES_DECRYPT); printf("\nCiphertext CFB: "); fprintBuffer_raw(stdout, (char*)ciphertext, sizeof(plaintext)); if (memcmp(deciphertext, plaintext, sizeof(plaintext)) == 0){ printf("\nRecovery: OK\n"); } else{ printf("\nRecovery: FAIL\n"); } return EXIT_SUCCESS; }
// As with read(), the documentation above is inconsistent with the // documentation for the write() system call. int bb_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) //modified this funtion { int retstat = 0, total = 0; char buf_new[size]; char indata[AES_BLOCK_SIZE]; char outdata[AES_BLOCK_SIZE]; if(encryption == 1) //if we use AES Encryption { while(total<size) { int i; for(i = 0; i<AES_BLOCK_SIZE && total+i<size; i++) //set 16 bytes chunks of buf as input data { indata[i] = buf[total+i]; } bytes_read = AES_BLOCK_SIZE; num = 0; memcpy( ivec , ivecstr, AES_BLOCK_SIZE); AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num, AES_ENCRYPT); //encrypt buf for(i = 0; i<AES_BLOCK_SIZE && total+i<size; i++) { buf_new[total+i] = outdata[i]; //set the encrypted output to buf_new } total+=AES_BLOCK_SIZE; } } else if(encryption == 0) //if we use simple cipher { int i=0; for(i=0;i<size;i++) { buf_new[i]=buf[i]+1; //encrypt buf by setting buf[i] as buf[i]+1 } } log_msg("\nbb_write(path=\"%s\", buf=0x%08x, size=%d, offset=%lld, fi=0x%08x)\n", path, buf, size, offset, fi ); // no need to get fpath on this one, since I work from fi->fh not the path log_fi(fi); return log_syscall("pwrite", pwrite(fi->fh, buf_new, size, offset), 0); //write encrypted data to file }
// I don't fully understand the documentation above -- it doesn't // match the documentation for the read() system call which says it // can return with anything up to the amount of data requested. nor // with the fusexmp code which returns the amount of data also // returned by read. int bb_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) //modified this funtion { int retstat = 0, total = 0; char indata[AES_BLOCK_SIZE]; char outdata[AES_BLOCK_SIZE]; log_msg("\nbb_read(path=\"%s\", buf=0x%08x, size=%d, offset=%lld, fi=0x%08x)\n", path, buf, size, offset, fi); // no need to get fpath on this one, since I work from fi->fh not the path log_fi(fi); retstat = log_syscall("pread", pread(fi->fh, buf, size, offset), 0); //read from the file if(encryption == 1) //if we use AES Encryption { while(total<size) { int i; for(i = 0; i<AES_BLOCK_SIZE && total+i<size; i++) //set 16 bytes chunks of buf as input data { indata[i] = buf[total+i]; } bytes_read = AES_BLOCK_SIZE; num = 0; memcpy( ivec , ivecstr, AES_BLOCK_SIZE); AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num, AES_DECRYPT); //decrypt buf for(i = 0; i<AES_BLOCK_SIZE && total+i<size; i++) //set the outdata from decrypt as buf { buf[total+i] = outdata[i]; } total+=AES_BLOCK_SIZE; } } else if (encryption == 0) //if we use simple cipher { int i=0; for(i=0;i<size;i++) //decrypt buf by setting buf to buf-1 { buf[i]=buf[i]-1; } } return retstat; }
int main(void) { int bytes_read, bytes_written; unsigned char indata[AES_BLOCK_SIZE]; unsigned char outdata[AES_BLOCK_SIZE]; /* ckey and ivec are the two 128-bits keys necesary to en- and recrypt your data. Note that ckey can be 192 or 256 bits as well */ unsigned char ckey[] = "thiskeyisverybad"; unsigned char ivec[] = "dontusethisinput"; FILE *ifp = fopen("/home/ashdharan/encrypt_file", "r"); FILE *ofp = fopen("/home/ashdharan/decrypt_file", "w"); /* data structure that contains the key itself */ AES_KEY key; /* set the decryption key */ AES_set_encrypt_key(ckey, 128, &key); int num = 16; while (1) { bytes_read = fread(indata, 1, AES_BLOCK_SIZE, ifp); AES_cfb128_encrypt(indata, outdata, bytes_read, &key, ivec, &num, AES_DECRYPT); bytes_written = fwrite(outdata, 1, bytes_read, ofp); if (bytes_read < AES_BLOCK_SIZE) break; } fclose(ifp); fclose(ofp); }
_SCAPI_NOT_CONFIGURED #endif /* NETSNMP_USE_INTERNAL_MD5 */ /*******************************************************************-o-****** * sc_encrypt * * Parameters: * privtype Type of privacy cryptographic transform. * *key Key bits for crypting. * keylen Length of key (buffer) in bytes. * *iv IV bits for crypting. * ivlen Length of iv (buffer) in bytes. * *plaintext Plaintext to crypt. * ptlen Length of plaintext. * *ciphertext Ciphertext to crypt. * *ctlen Length of ciphertext. * * Returns: * SNMPERR_SUCCESS Success. * SNMPERR_SC_NOT_CONFIGURED Encryption is not supported. * SNMPERR_SC_GENERAL_FAILURE Any other error * * * Encrypt plaintext into ciphertext using key and iv. * * ctlen contains actual number of crypted bytes in ciphertext upon * successful return. */ int sc_encrypt(const oid * privtype, size_t privtypelen, u_char * key, u_int keylen, u_char * iv, u_int ivlen, u_char * plaintext, u_int ptlen, u_char * ciphertext, size_t * ctlen) #if defined(NETSNMP_USE_OPENSSL) { int rval = SNMPERR_SUCCESS; u_int properlength = 0, properlength_iv = 0; u_char pad_block[128]; /* bigger than anything I need */ u_char my_iv[128]; /* ditto */ int pad, plast, pad_size = 0; int have_trans; #ifndef NETSNMP_DISABLE_DES #ifdef OLD_DES DES_key_schedule key_sch; #else DES_key_schedule key_sched_store; DES_key_schedule *key_sch = &key_sched_store; #endif DES_cblock key_struct; #endif #ifdef HAVE_AES AES_KEY aes_key; int new_ivlen = 0; #endif DEBUGTRACE; /* * Sanity check. */ #if !defined(NETSNMP_ENABLE_SCAPI_AUTHPRIV) snmp_log(LOG_ERR, "Encryption support not enabled.\n"); return SNMPERR_SC_NOT_CONFIGURED; #endif if (!privtype || !key || !iv || !plaintext || !ciphertext || !ctlen || (keylen <= 0) || (ivlen <= 0) || (ptlen <= 0) || (*ctlen <= 0) || (privtypelen != USM_LENGTH_OID_TRANSFORM)) { QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); } else if (ptlen > *ctlen) { QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); } #ifdef NETSNMP_ENABLE_TESTING_CODE { size_t buf_len = 128, out_len = 0; u_char *buf = (u_char *) malloc(buf_len); if (buf != NULL) { if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, iv, ivlen)) { DEBUGMSGTL(("scapi", "encrypt: IV: %s/", buf)); } else { DEBUGMSGTL(("scapi", "encrypt: IV: %s [TRUNCATED]/", buf)); } out_len = 0; if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, key, keylen)) { DEBUGMSG(("scapi", "%s\n", buf)); } else { DEBUGMSG(("scapi", "%s [TRUNCATED]\n", buf)); } out_len = 0; if (sprint_realloc_hexstring(&buf, &buf_len, &out_len, 1, plaintext, 16)) { DEBUGMSGTL(("scapi", "encrypt: string: %s\n", buf)); } else { DEBUGMSGTL(("scapi", "encrypt: string: %s [TRUNCATED]\n", buf)); } free(buf); } else { DEBUGMSGTL(("scapi", "encrypt: malloc fail for debug output\n")); } } #endif /* NETSNMP_ENABLE_TESTING_CODE */ /* * Determine privacy transform. */ have_trans = 0; #ifndef NETSNMP_DISABLE_DES if (ISTRANSFORM(privtype, DESPriv)) { properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES); properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_1DES_IV); pad_size = properlength; have_trans = 1; } #endif #ifdef HAVE_AES if (ISTRANSFORM(privtype, AESPriv)) { properlength = BYTESIZE(SNMP_TRANS_PRIVLEN_AES); properlength_iv = BYTESIZE(SNMP_TRANS_PRIVLEN_AES_IV); have_trans = 1; } #endif if (!have_trans) { QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); } if ((keylen < properlength) || (ivlen < properlength_iv)) { QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); } memset(my_iv, 0, sizeof(my_iv)); #ifndef NETSNMP_DISABLE_DES if (ISTRANSFORM(privtype, DESPriv)) { /* * now calculate the padding needed */ pad = pad_size - (ptlen % pad_size); plast = (int) ptlen - (pad_size - pad); if (pad == pad_size) pad = 0; if (ptlen + pad > *ctlen) { QUITFUN(SNMPERR_GENERR, sc_encrypt_quit); /* not enough space */ } if (pad > 0) { /* copy data into pad block if needed */ memcpy(pad_block, plaintext + plast, pad_size - pad); memset(&pad_block[pad_size - pad], pad, pad); /* filling in padblock */ } memcpy(key_struct, key, sizeof(key_struct)); (void) DES_key_sched(&key_struct, key_sch); memcpy(my_iv, iv, ivlen); /* * encrypt the data */ DES_ncbc_encrypt(plaintext, ciphertext, plast, key_sch, (DES_cblock *) my_iv, DES_ENCRYPT); if (pad > 0) { /* * then encrypt the pad block */ DES_ncbc_encrypt(pad_block, ciphertext + plast, pad_size, key_sch, (DES_cblock *) my_iv, DES_ENCRYPT); *ctlen = plast + pad_size; } else { *ctlen = plast; } } #endif #ifdef HAVE_AES if (ISTRANSFORM(privtype, AESPriv)) { (void) AES_set_encrypt_key(key, properlength*8, &aes_key); memcpy(my_iv, iv, ivlen); /* * encrypt the data */ AES_cfb128_encrypt(plaintext, ciphertext, ptlen, &aes_key, my_iv, &new_ivlen, AES_ENCRYPT); *ctlen = ptlen; } #endif sc_encrypt_quit: /* * clear memory just in case */ memset(my_iv, 0, sizeof(my_iv)); memset(pad_block, 0, sizeof(pad_block)); #ifndef NETSNMP_DISABLE_DES memset(key_struct, 0, sizeof(key_struct)); #ifdef OLD_DES memset(&key_sch, 0, sizeof(key_sch)); #else memset(&key_sched_store, 0, sizeof(key_sched_store)); #endif #endif #ifdef HAVE_AES memset(&aes_key,0,sizeof(aes_key)); #endif return rval; } /* end sc_encrypt() */
static int check(unsigned char *keydata, int ks) { // Decrypt first data block in order to check the first two bits of // the MPI. If they are correct, there's a good chance that the // password is correct, too. unsigned char ivec[32]; unsigned char out[BIG_ENOUGH * 2] = { 0 }; int tmp = 0; uint32_t num_bits; int checksumOk; int i; // Quick Hack memcpy(ivec, cur_salt->iv, blockSize(cur_salt->cipher_algorithm)); switch (cur_salt->cipher_algorithm) { case CIPHER_IDEA: { IDEA_KEY_SCHEDULE iks; JtR_idea_set_encrypt_key(keydata, &iks); JtR_idea_cfb64_encrypt(cur_salt->data, out, SALT_LENGTH, &iks, ivec, &tmp, IDEA_DECRYPT); } break; case CIPHER_CAST5: { CAST_KEY ck; CAST_set_key(&ck, ks, keydata); CAST_cfb64_encrypt(cur_salt->data, out, CAST_BLOCK, &ck, ivec, &tmp, CAST_DECRYPT); } break; case CIPHER_BLOWFISH: { BF_KEY ck; BF_set_key(&ck, ks, keydata); BF_cfb64_encrypt(cur_salt->data, out, BF_BLOCK, &ck, ivec, &tmp, BF_DECRYPT); } break; case CIPHER_AES128: case CIPHER_AES192: case CIPHER_AES256: { AES_KEY ck; AES_set_encrypt_key(keydata, ks * 8, &ck); AES_cfb128_encrypt(cur_salt->data, out, AES_BLOCK_SIZE, &ck, ivec, &tmp, AES_DECRYPT); } break; case CIPHER_3DES: { DES_cblock key1, key2, key3; DES_cblock divec; DES_key_schedule ks1, ks2, ks3; int num = 0; memcpy(key1, keydata + 0, 8); memcpy(key2, keydata + 8, 8); memcpy(key3, keydata + 16, 8); memcpy(divec, ivec, 8); DES_set_key((DES_cblock *)key1, &ks1); DES_set_key((DES_cblock *)key2, &ks2); DES_set_key((DES_cblock *)key3, &ks3); DES_ede3_cfb64_encrypt(cur_salt->data, out, SALT_LENGTH, &ks1, &ks2, &ks3, &divec, &num, DES_DECRYPT); } break; default: printf("(check) Unknown Cipher Algorithm %d ;(\n", cur_salt->cipher_algorithm); break; } num_bits = ((out[0] << 8) | out[1]); if (num_bits < MIN_BN_BITS || num_bits > cur_salt->bits) { return 0; } // Decrypt all data memcpy(ivec, cur_salt->iv, blockSize(cur_salt->cipher_algorithm)); tmp = 0; switch (cur_salt->cipher_algorithm) { case CIPHER_IDEA: { IDEA_KEY_SCHEDULE iks; JtR_idea_set_encrypt_key(keydata, &iks); JtR_idea_cfb64_encrypt(cur_salt->data, out, cur_salt->datalen, &iks, ivec, &tmp, IDEA_DECRYPT); } break; case CIPHER_CAST5: { CAST_KEY ck; CAST_set_key(&ck, ks, keydata); CAST_cfb64_encrypt(cur_salt->data, out, cur_salt->datalen, &ck, ivec, &tmp, CAST_DECRYPT); } break; case CIPHER_BLOWFISH: { BF_KEY ck; BF_set_key(&ck, ks, keydata); BF_cfb64_encrypt(cur_salt->data, out, cur_salt->datalen, &ck, ivec, &tmp, BF_DECRYPT); } break; case CIPHER_AES128: case CIPHER_AES192: case CIPHER_AES256: { AES_KEY ck; AES_set_encrypt_key(keydata, ks * 8, &ck); AES_cfb128_encrypt(cur_salt->data, out, cur_salt->datalen, &ck, ivec, &tmp, AES_DECRYPT); } break; case CIPHER_3DES: { DES_cblock key1, key2, key3; DES_cblock divec; DES_key_schedule ks1, ks2, ks3; int num = 0; memcpy(key1, keydata + 0, 8); memcpy(key2, keydata + 8, 8); memcpy(key3, keydata + 16, 8); memcpy(divec, ivec, 8); DES_set_key((DES_cblock *) key1, &ks1); DES_set_key((DES_cblock *) key2, &ks2); DES_set_key((DES_cblock *) key3, &ks3); DES_ede3_cfb64_encrypt(cur_salt->data, out, cur_salt->datalen, &ks1, &ks2, &ks3, &divec, &num, DES_DECRYPT); } break; default: break; } // Verify checksumOk = 0; switch (cur_salt->usage) { case 254: { uint8_t checksum[SHA_DIGEST_LENGTH]; SHA_CTX ctx; SHA1_Init(&ctx); SHA1_Update(&ctx, out, cur_salt->datalen - SHA_DIGEST_LENGTH); SHA1_Final(checksum, &ctx); if (memcmp(checksum, out + cur_salt->datalen - SHA_DIGEST_LENGTH, SHA_DIGEST_LENGTH) == 0) return 1; /* we have a 20 byte verifier ;) */ else return 0; } break; case 0: case 255: { // https://tools.ietf.org/html/rfc4880#section-3.7.2 uint16_t sum = 0; for (i = 0; i < cur_salt->datalen - 2; i++) { sum += out[i]; } if (sum == ((out[cur_salt->datalen - 2] << 8) | out[cur_salt->datalen - 1])) { checksumOk = 1; } } break; default: break; } // If the checksum is ok, try to parse the first MPI of the private key // Stop relying on checksum altogether, GnuPG ignores it (after // documenting why though!) if (checksumOk) { BIGNUM *b = NULL; uint32_t blen = (num_bits + 7) / 8; int ret; if (cur_salt->datalen == 24 && blen != 20) /* verifier 1 */ return 0; if (blen < cur_salt->datalen && ((b = BN_bin2bn(out + 2, blen, NULL)) != NULL)) { char *str = BN_bn2hex(b); DSA dsa; ElGamal_secret_key elg; RSA_secret_key rsa; if (strlen(str) != blen * 2) { /* verifier 2 */ OPENSSL_free(str); return 0; } OPENSSL_free(str); if (cur_salt->pk_algorithm == 17) { /* DSA check */ dsa.p = BN_bin2bn(cur_salt->p, cur_salt->pl, NULL); // puts(BN_bn2hex(dsa.p)); dsa.q = BN_bin2bn(cur_salt->q, cur_salt->ql, NULL); // puts(BN_bn2hex(dsa.q)); dsa.g = BN_bin2bn(cur_salt->g, cur_salt->gl, NULL); // puts(BN_bn2hex(dsa.g)); dsa.priv_key = b; dsa.pub_key = BN_bin2bn(cur_salt->y, cur_salt->yl, NULL); // puts(BN_bn2hex(dsa.pub_key)); ret = check_dsa_secret_key(&dsa); /* verifier 3 */ if (ret != 0) return 0; } if (cur_salt->pk_algorithm == 16 || cur_salt->pk_algorithm == 20) { /* ElGamal check */ elg.p = BN_bin2bn(cur_salt->p, cur_salt->pl, NULL); // puts(BN_bn2hex(elg.p)); elg.g = BN_bin2bn(cur_salt->g, cur_salt->gl, NULL); // puts(BN_bn2hex(elg.g)); elg.x = b; // puts(BN_bn2hex(elg.x)); elg.y = BN_bin2bn(cur_salt->y, cur_salt->yl, NULL); // puts(BN_bn2hex(elg.y)); ret = check_elg_secret_key(&elg); /* verifier 3 */ if (ret != 0) return 0; } if (cur_salt->pk_algorithm == 1) { /* RSA check */ // http://www.ietf.org/rfc/rfc4880.txt int length = 0; length += give_multi_precision_integer(out, length, &cur_salt->dl, cur_salt->d); length += give_multi_precision_integer(out, length, &cur_salt->pl, cur_salt->p); length += give_multi_precision_integer(out, length, &cur_salt->ql, cur_salt->q); rsa.n = BN_bin2bn(cur_salt->n, cur_salt->nl, NULL); rsa.p = BN_bin2bn(cur_salt->p, cur_salt->pl, NULL); rsa.q = BN_bin2bn(cur_salt->q, cur_salt->ql, NULL); ret = check_rsa_secret_key(&rsa); if (ret != 0) return 0; } return 1; } } return 0; }
virtual void decrypt(const unsigned char* in, unsigned char* out, std::size_t length) { assert(in && out); AES_cfb128_encrypt(in, out, length, &this->aes_ctx, this->ivec, &this->num, AES_DECRYPT); }
// Checks if the given password is valid bool Tester::check(const Memblock &mblock) { const String2Key &s2k = m_key.string2Key(); int32_t tmp = 0; // Generate key from password s2k.generateKey(mblock, m_keydata, m_keySize); // Decrypt first data block in order to check the first two bits of // the MPI. If they are correct, there's a good chance that the // password is correct, too. #if 1 memcpy(m_ivec, s2k.ivec(), m_blockSize); switch (m_cipher) { case CryptUtils::CIPHER_CAST5: { CAST_KEY ck; CAST_set_key(&ck, m_keySize, m_keydata); CAST_cfb64_encrypt(m_in, m_out, CAST_BLOCK, &ck, m_ivec, &tmp, CAST_DECRYPT); } break; case CryptUtils::CIPHER_BLOWFISH: { BF_KEY ck; BF_set_key(&ck, m_keySize, m_keydata); BF_cfb64_encrypt(m_in, m_out, BF_BLOCK, &ck, m_ivec, &tmp, BF_DECRYPT); } break; case CryptUtils::CIPHER_AES128: case CryptUtils::CIPHER_AES192: case CryptUtils::CIPHER_AES256: { AES_KEY ck; AES_set_encrypt_key(m_keydata, m_keySize * 8, &ck); AES_cfb128_encrypt(m_in, m_out, AES_BLOCK_SIZE, &ck, m_ivec, &tmp, AES_DECRYPT); } break; default: break; } uint32_t num_bits = ((m_out[0] << 8) | m_out[1]); if (num_bits < MIN_BN_BITS || num_bits > m_bits) { return false; } #endif // Decrypt all data memcpy(m_ivec, s2k.ivec(), m_blockSize); tmp = 0; switch (m_cipher) { case CryptUtils::CIPHER_CAST5: { CAST_KEY ck; CAST_set_key(&ck, m_keySize, m_keydata); CAST_cfb64_encrypt(m_in, m_out, m_datalen, &ck, m_ivec, &tmp, CAST_DECRYPT); } break; case CryptUtils::CIPHER_BLOWFISH: { BF_KEY ck; BF_set_key(&ck, m_keySize, m_keydata); BF_cfb64_encrypt(m_in, m_out, m_datalen, &ck, m_ivec, &tmp, BF_DECRYPT); } break; case CryptUtils::CIPHER_AES128: case CryptUtils::CIPHER_AES192: case CryptUtils::CIPHER_AES256: { AES_KEY ck; AES_set_encrypt_key(m_keydata, m_keySize * 8, &ck); AES_cfb128_encrypt(m_in, m_out, m_datalen, &ck, m_ivec, &tmp, AES_DECRYPT); } break; default: break; } // Verify bool checksumOk = false; switch (s2k.usage()) { case 254: { uint8_t checksum[SHA_DIGEST_LENGTH]; pgpry_SHA_CTX ctx; pgpry_SHA1_Init(&ctx); pgpry_SHA1_Update(&ctx, m_out, m_datalen - SHA_DIGEST_LENGTH); pgpry_SHA1_Final(checksum, &ctx); if (memcmp(checksum, m_out + m_datalen - SHA_DIGEST_LENGTH, SHA_DIGEST_LENGTH) == 0) { checksumOk = true; } } break; case 0: case 255: { uint16_t sum = 0; for (uint32_t i = 0; i < m_datalen - 2; i++) { sum += m_out[i]; } if (sum == ((m_out[m_datalen - 2] << 8) | m_out[m_datalen - 1])) { checksumOk = true; } } break; default: break; } // If the checksum is ok, try to parse the first MPI of the private key if (checksumOk) { BIGNUM *b = NULL; uint32_t blen = (num_bits + 7) / 8; if (blen < m_datalen && ((b = BN_bin2bn(m_out + 2, blen, NULL)) != NULL)) { BN_free(b); return true; } } return false; }
static void aes_cfb_decrypt(ops_crypt_t *crypt,void *out,const void *in, size_t count) { AES_cfb128_encrypt(in,out,count, crypt->encrypt_key, crypt->iv, (int *)&crypt->num, AES_DECRYPT); }