static int ede_cfb64_test(unsigned char *cfb_cipher) { DES_key_schedule ks; int err = 0, i, n; DES_set_key_checked(&cfb_key, &ks); memcpy(cfb_tmp, cfb_iv, sizeof(cfb_iv)); n = 0; DES_ede3_cfb64_encrypt(plain, cfb_buf1, 12, &ks, &ks, &ks, &cfb_tmp, &n, DES_ENCRYPT); DES_ede3_cfb64_encrypt(&(plain[12]), &(cfb_buf1[12]), sizeof(plain) - 12, &ks, &ks, &ks, &cfb_tmp, &n, DES_ENCRYPT); if (memcmp(cfb_cipher, cfb_buf1, sizeof(plain)) != 0) { err = 1; printf("ede_cfb_encrypt encrypt error\n"); for (i = 0; i < 24; i += 8) printf("%s\n", pt(&(cfb_buf1[i]))); } memcpy(cfb_tmp, cfb_iv, sizeof(cfb_iv)); n = 0; DES_ede3_cfb64_encrypt(cfb_buf1, cfb_buf2, (long)17, &ks, &ks, &ks, &cfb_tmp, &n, DES_DECRYPT); DES_ede3_cfb64_encrypt(&(cfb_buf1[17]), &(cfb_buf2[17]), sizeof(plain) - 17, &ks, &ks, &ks, &cfb_tmp, &n, DES_DECRYPT); if (memcmp(plain, cfb_buf2, sizeof(plain)) != 0) { err = 1; printf("ede_cfb_encrypt decrypt error\n"); for (i = 0; i < 24; i += 8) printf("%s\n", pt(&(cfb_buf2[i]))); } return (err); }
/* * The input and output encrypted as though 64bit cfb mode is being used. * The extra state information to record how much of the 64bit block we have * used is contained in *num; */ void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out, long length, DES_key_schedule *ks1, DES_key_schedule *ks2, DES_key_schedule *ks3, DES_cblock *ivec, int *num, int enc) { DES_LONG v0, v1; long l = length; int n = *num; DES_LONG ti[2]; unsigned char *iv, c, cc; iv = &(*ivec)[0]; if (enc) { while (l--) { if (n == 0) { c2l(iv, v0); c2l(iv, v1); ti[0] = v0; ti[1] = v1; DES_encrypt3(ti, ks1, ks2, ks3); v0 = ti[0]; v1 = ti[1]; iv = &(*ivec)[0]; l2c(v0, iv); l2c(v1, iv); iv = &(*ivec)[0]; } c = *(in++) ^ iv[n]; *(out++) = c; iv[n] = c; n = (n + 1) & 0x07; } } else { while (l--) { if (n == 0) { c2l(iv, v0); c2l(iv, v1); ti[0] = v0; ti[1] = v1; DES_encrypt3(ti, ks1, ks2, ks3); v0 = ti[0]; v1 = ti[1]; iv = &(*ivec)[0]; l2c(v0, iv); l2c(v1, iv); iv = &(*ivec)[0]; } cc = *(in++); c = iv[n]; iv[n] = cc; *(out++) = c ^ cc; n = (n + 1) & 0x07; } } v0 = v1 = ti[0] = ti[1] = c = cc = 0; *num = n; } #ifdef undef /* MACRO */ void DES_ede2_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, DES_key_schedule ks1, DES_key_schedule ks2, DES_cblock (*ivec), int *num, int enc) { DES_ede3_cfb64_encrypt(in, out, length, ks1, ks2, ks1, ivec, num, enc); }
static int des_ede_cfb64_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, unsigned int inl) { DES_ede3_cfb64_encrypt(in, out, (long)inl, &data(ctx)->ks1, &data(ctx)->ks2, &data(ctx)->ks3, (DES_cblock *)ctx->iv, &ctx->num, ctx->encrypt); return 1; }
void _ossl_old_des_ede3_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, des_key_schedule ks1, des_key_schedule ks2, des_key_schedule ks3, _ossl_old_des_cblock *ivec, int *num, int enc) { DES_ede3_cfb64_encrypt(in, out, length, (DES_key_schedule *)ks1, (DES_key_schedule *)ks2, (DES_key_schedule *)ks3, ivec, num, enc); }
void TripleDESCryptor::Decrypt(const char* input, char* output, size_t length) const { int n = 0; DES_cblock ivec = {0}; DES_key_schedule ks1(ks1_); DES_key_schedule ks2(ks2_); DES_key_schedule ks3(ks3_); DES_ede3_cfb64_encrypt((const unsigned char*)input, (unsigned char*)output, length, &ks1, &ks2, &ks3, &ivec, &n, DES_DECRYPT); }
static void tripledes_cfb_decrypt(pgp_crypt_t *crypt, void *out, const void *in, size_t count) { DES_key_schedule *keys = crypt->encrypt_key; DES_ede3_cfb64_encrypt(in, out, (long)count, &keys[0], &keys[1], &keys[2], (DES_cblock *)(void *)crypt->iv, &crypt->num, DES_DECRYPT); }
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; }
int main(void) { int i; BIO* bio_out; DES_cblock key1; DES_cblock key2; DES_cblock key3; DES_key_schedule schedule1; DES_key_schedule schedule2; DES_key_schedule schedule3; unsigned char const iv_data[DES_KEY_SZ] = { 0xcc, 0xfe, 0xcd, 0x3e, 0x21, 0xde, 0x1c, 0x31 }; unsigned char iv[DES_KEY_SZ]; char* data = "The worthwhile problems are the ones you can" "really solve or help solve, the ones you can" "really contribute something to. No " "problem is too small or too trivial if we " "can really do something about it." "- Richard Feynman"; int length = strlen(data); /* Intialise to '0' to indicate that '0' bytes of the IV has been used */ int num = 0; char* ciphertext = (char*) malloc(sizeof(char) * length); char* plaintext = (char*) malloc(sizeof(char) * length); /* Copy the IV data to the IV array. The IV array will be updated by the DES_cfb64_encrypt call.*/ memcpy(iv, iv_data, DES_KEY_SZ); /* In this example, we shall be generating a random key. Before this can * happen, we must seed the PRNG. OpenSSL ensures that the PRNG is transparently * seeded on systems that provide the "/dev/urandom" file. */ /* Cater for seeding the PRNG in Windows */ #ifdef OPENSSL_SYS_WIN32 /* Add entropy */ #endif /* Generate the random keys (as expected by DES) */ DES_random_key(&key1); DES_random_key(&key2); DES_random_key(&key3); /* Check the odd parity of the key and its weakness. In doing so, * convert to the architecture dependent format. */ DES_set_key_checked(&key1, &schedule1); DES_set_key_checked(&key2, &schedule2); DES_set_key_checked(&key3, &schedule3); DES_ede3_cfb64_encrypt(data, ciphertext, length, &schedule1, &schedule2, &schedule3, (DES_cblock*)iv, &num, DES_ENCRYPT); bio_out = BIO_new_fp(stdout, BIO_NOCLOSE); BIO_printf(bio_out, "Original plaintext: %s\n\n", data); BIO_printf(bio_out, "Ciphertext: "); /* print out the ciphertext */ for (i = 0; i < length; i++) BIO_printf(bio_out, "%02x", ((unsigned char*)ciphertext)[i]); BIO_printf(bio_out, "\n\n"); /* start the decryption process */ /* Re-intialise to '0' to indicate that '0' bytes of the IV has been used */ num = 0; /* First, copy the original IV data back to the IV array - as it was * overwritten during the encryption process */ memcpy(iv, iv_data, DES_KEY_SZ); DES_ede3_cfb64_encrypt(ciphertext, plaintext, length, &schedule1, &schedule2, &schedule3, (DES_cblock*)iv, &num, DES_DECRYPT); BIO_printf(bio_out, "Recovered plaintext: "); /* print out the plaintext */ for (i = 0; i < length; i++) BIO_printf(bio_out, "%c", ((unsigned char*)plaintext)[i]); BIO_printf(bio_out, "\n"); BIO_free(bio_out); free(ciphertext); free(plaintext); return 0; }