char* decrypt(char *private_key, char *ciphertext){ gcry_error_t error; gcry_sexp_t data = sexp_new(ciphertext); gcry_sexp_t private_sexp = sexp_new(private_key); gcry_sexp_t r_plain; struct timeval timer; timer_start(&timer); if ((error = gcry_pk_decrypt(&r_plain, data, private_sexp))) { printf("Error in gcry_pk_decrypt(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } timer_poll("\nSoftware decrypt: %d.%06d seconds\n", &timer); gcry_mpi_t r_mpi = gcry_sexp_nth_mpi(r_plain, 0, GCRYMPI_FMT_USG); unsigned char *plaintext; size_t plaintext_size; if ((error = gcry_mpi_aprint(GCRYMPI_FMT_HEX, &plaintext, &plaintext_size, r_mpi))) { printf("Error in gcry_mpi_aprint(): %s\nSource: %s\n", gcry_strerror(error), gcry_strsource(error)); exit(1); } // Return type hack return (char *) plaintext; }
CK_RV gkm_rsa_mechanism_decrypt (gcry_sexp_t sexp, EggPadding padding, CK_BYTE_PTR encrypted, CK_ULONG n_encrypted, CK_BYTE_PTR data, CK_ULONG_PTR n_data) { gcry_sexp_t splain, sdata; gcry_error_t gcry; guint nbits; CK_RV rv; g_return_val_if_fail (sexp, CKR_GENERAL_ERROR); g_return_val_if_fail (n_data, CKR_ARGUMENTS_BAD); g_return_val_if_fail (encrypted, CKR_ARGUMENTS_BAD); nbits = gcry_pk_get_nbits (sexp); g_return_val_if_fail (nbits > 0, CKR_GENERAL_ERROR); /* Just want to know the length */ if (!data) { *n_data = (nbits + 7) / 8; return CKR_OK; } if (n_encrypted != (nbits + 7) / 8) return CKR_DATA_LEN_RANGE; /* Prepare the input s expression */ rv = gkm_crypto_data_to_sexp ("(enc-val (flags) (rsa (a %m)))", nbits, NULL, encrypted, n_encrypted, &sdata); if (rv != CKR_OK) return rv; /* Do the magic */ gcry = gcry_pk_decrypt (&splain, sdata, sexp); gcry_sexp_release (sdata); /* TODO: Certain codes should be returned (data too big etc... ) */ if (gcry) { g_message ("decrypting of the data failed: %s", gcry_strerror (gcry)); return CKR_FUNCTION_FAILED; } /* Now extract and send it back out */ rv = gkm_crypto_sexp_to_data (splain, nbits, data, n_data, padding, "value", NULL); gcry_sexp_release (splain); return rv; }
int p2p_decrypt(unsigned char *buf, size_t buflen, char *msg, size_t msglen, gcry_sexp_t d_key) { size_t err; gcry_sexp_t ciph; gcry_mpi_t data_mpi; gcry_mpi_scan(&data_mpi, GCRYMPI_FMT_PGP, buf, buflen, &err); gcry_sexp_build(&ciph, &err, "(enc-val (flags pkcs1) (rsa (a %M)))", data_mpi); gcry_mpi_release(data_mpi); gcry_sexp_t data_sexp; gcry_pk_decrypt(&data_sexp, ciph, d_key); gcry_sexp_release(ciph); gcry_sexp_t data = gcry_sexp_cdr(data_sexp); gcry_sexp_release(data_sexp); size_t len; const char *msg_data = gcry_sexp_nth_data(data, 0, &len); len = msglen > len ? len : msglen; memcpy(msg, msg_data, len); gcry_sexp_release(data); return len; }
/** * cdk_pk_decrypt: * @sk: the secret key * @pke: public key encrypted packet * @r_sk: the object to store the plain session key * * Decrypt the encrypted session key from @pke into @r_sk. **/ cdk_error_t cdk_pk_decrypt (cdk_seckey_t sk, cdk_pkt_pubkey_enc_t pke, gcry_mpi_t *r_sk) { gcry_sexp_t s_data = NULL, s_skey = NULL, s_plain = NULL; cdk_error_t rc; gcry_error_t err; if (!sk || !r_sk || !pke) return CDK_Inv_Value; if (!is_unprotected (sk)) return CDK_Inv_Mode; *r_sk = NULL; rc = seckey_to_sexp (&s_skey, sk); if (rc) return rc; rc = pubenc_to_sexp (&s_data, pke); if (rc) { gcry_sexp_release (s_skey); return rc; } err = gcry_pk_decrypt (&s_plain, s_data, s_skey); if (err) rc = map_gcry_error (err); else *r_sk = gcry_sexp_nth_mpi (s_plain, 0, 0); gcry_sexp_release (s_data); gcry_sexp_release (s_skey); gcry_sexp_release (s_plain); return rc; }
static int _gnutls_pk_decrypt (int algo, mpi_t * resarr, mpi_t data, mpi_t * pkey, int pkey_len) { gcry_sexp_t s_plain, s_data, s_pkey; int rc = -1; /* make a sexp from pkey */ switch (algo) { case GCRY_PK_RSA: if (pkey_len >= 6) rc = gcry_sexp_build (&s_pkey, NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", pkey[0], pkey[1], pkey[2], pkey[3], pkey[4], pkey[5]); break; default: gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } if (rc != 0) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* put the data into a simple list */ if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { gnutls_assert (); gcry_sexp_release (s_pkey); return GNUTLS_E_INTERNAL_ERROR; } /* pass it to libgcrypt */ rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey); gcry_sexp_release (s_data); gcry_sexp_release (s_pkey); if (rc != 0) { gnutls_assert (); return GNUTLS_E_PK_DECRYPTION_FAILED; } else { /* add better error handling or make gnupg use S-Exp directly */ resarr[0] = gcry_sexp_nth_mpi (s_plain, 0, 0); if (resarr[0] == NULL) { gnutls_assert (); gcry_sexp_release (s_plain); return GNUTLS_E_INTERNAL_ERROR; } } gcry_sexp_release (s_plain); return rc; }
/** * ntfs_raw_fek_decrypt - * * Note: decrypting into the input buffer. */ static unsigned ntfs_raw_fek_decrypt(u8 *fek, u32 fek_size, ntfs_rsa_private_key rsa_key) { gcry_mpi_t fek_mpi; gcry_sexp_t fek_sexp, fek_sexp2; gcry_error_t err; size_t size, padding; /* Reverse the raw FEK. */ ntfs_buffer_reverse(fek, fek_size); /* Convert the FEK to internal MPI format. */ err = gcry_mpi_scan(&fek_mpi, GCRYMPI_FMT_USG, fek, fek_size, NULL); if (err != GPG_ERR_NO_ERROR) { ntfs_log_error("Failed to convert file encryption key to " "internal MPI format: %s\n", gcry_strerror(err)); return 0; } /* Create an internal S-expression from the FEK. */ err = gcry_sexp_build(&fek_sexp, NULL, "(enc-val (flags) (rsa (a %m)))", fek_mpi); gcry_mpi_release(fek_mpi); if (err != GPG_ERR_NO_ERROR) { ntfs_log_error("Failed to create internal S-expression of " "the file encryption key: %s\n", gcry_strerror(err)); return 0; } /* Decrypt the FEK. */ err = gcry_pk_decrypt(&fek_sexp2, fek_sexp, (gcry_sexp_t)rsa_key); gcry_sexp_release(fek_sexp); if (err != GPG_ERR_NO_ERROR) { ntfs_log_error("Failed to decrypt the file encryption key: " "%s\n", gcry_strerror(err)); return 0; } /* Extract the actual FEK from the decrypted raw S-expression. */ fek_sexp = gcry_sexp_find_token(fek_sexp2, "value", 0); gcry_sexp_release(fek_sexp2); if (!fek_sexp) { ntfs_log_error("Failed to find the decrypted file encryption " "key in the internal S-expression.\n"); return 0; } /* Convert the decrypted FEK S-expression into MPI format. */ fek_mpi = gcry_sexp_nth_mpi(fek_sexp, 1, GCRYMPI_FMT_USG); gcry_sexp_release(fek_sexp); if (!fek_mpi) { ntfs_log_error("Failed to convert the decrypted file " "encryption key S-expression to internal MPI " "format.\n"); return 0; } /* Convert the decrypted FEK from MPI format to binary data. */ err = gcry_mpi_print(GCRYMPI_FMT_USG, fek, fek_size, &size, fek_mpi); gcry_mpi_release(fek_mpi); if (err != GPG_ERR_NO_ERROR || !size) { ntfs_log_error("Failed to convert decrypted file encryption " "key from internal MPI format to binary data: " "%s\n", gcry_strerror(err)); return 0; } /* * Finally, remove the PKCS#1 padding and return the size of the * decrypted FEK. */ padding = strnlen((char *)fek, size) + 1; if (padding > size) { ntfs_log_error("Failed to remove PKCS#1 padding from " "decrypted file encryption key.\n"); return 0; } size -= padding; memmove(fek, fek + padding, size); return size; }
static int _wrap_gcry_pk_decrypt (gnutls_pk_algorithm_t algo, gnutls_datum_t * plaintext, const gnutls_datum_t * ciphertext, const gnutls_pk_params_st * pk_params) { gcry_sexp_t s_plain = NULL, s_data = NULL, s_pkey = NULL; int rc = -1; int ret; bigint_t data, res; if (_gnutls_mpi_scan_nz (&data, ciphertext->data, ciphertext->size) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* make a sexp from pkey */ switch (algo) { case GNUTLS_PK_RSA: if (pk_params->params_nr >= 6) rc = gcry_sexp_build (&s_pkey, NULL, "(private-key(rsa((n%m)(e%m)(d%m)(p%m)(q%m)(u%m))))", pk_params->params[0], pk_params->params[1], pk_params->params[2], pk_params->params[3], pk_params->params[4], pk_params->params[5]); break; default: gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* put the data into a simple list */ if (gcry_sexp_build (&s_data, NULL, "(enc-val(rsa(a%m)))", data)) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } /* pass it to libgcrypt */ rc = gcry_pk_decrypt (&s_plain, s_data, s_pkey); if (rc != 0) { gnutls_assert (); ret = GNUTLS_E_PK_DECRYPTION_FAILED; goto cleanup; } res = gcry_sexp_nth_mpi (s_plain, 0, GCRYMPI_FMT_USG); if (res == NULL) { gnutls_assert (); ret = GNUTLS_E_INTERNAL_ERROR; goto cleanup; } ret = _gnutls_mpi_dprint_size (res, plaintext, ciphertext->size); _gnutls_mpi_release (&res); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_mpi_release (&data); if (s_plain) gcry_sexp_release (s_plain); if (s_data) gcry_sexp_release (s_data); if (s_pkey) gcry_sexp_release (s_pkey); return ret; }
/* decrypts the RSA encrypted text read from the XML file, * and saves the AES key and the other needed info * uses libgcrypt for decryption */ int AESKey::decryptRSA( string s_cipher_text_b64 ) { RSAKey rsa_key( this->p_demux ); unsigned char *ps_cipher_text = NULL; unsigned char *ps_plain_text = NULL; gcry_mpi_t cipher_text_mpi = NULL; gcry_sexp_t cipher_text_sexp = NULL; gcry_sexp_t plain_text_sexp = NULL; gcry_mpi_t plain_text_mpi = NULL; gcry_sexp_t tmp_sexp = NULL; gcry_error_t err; size_t length; int i_ret = VLC_EGENERIC; /* get RSA private key file path */ if( rsa_key.setPath() ) goto end; /* read private key from file */ if( rsa_key.readPEM() ) goto end; /* remove spaces and newlines from encoded cipher text * (usually added for indentation in XML files) * */ try { s_cipher_text_b64.erase( remove_if( s_cipher_text_b64.begin(), s_cipher_text_b64.end(), static_cast<int(*)(int)>(isspace) ), s_cipher_text_b64.end() ); } catch( ... ) { msg_Err( this->p_demux, "error while handling string" ); goto end; } /* decode cipher from BASE64 to binary */ if( ! ( length = vlc_b64_decode_binary( &ps_cipher_text, s_cipher_text_b64.c_str() ) ) ) { msg_Err( this->p_demux, "could not decode cipher from Base64" ); goto end; } /* initialize libgcrypt */ vlc_gcrypt_init (); /* create S-expression for ciphertext */ if( ( err = gcry_mpi_scan( &cipher_text_mpi, GCRYMPI_FMT_USG, ps_cipher_text, 256, NULL ) ) ) { msg_Err( this->p_demux, "could not scan MPI from cipher text: %s", gcry_strerror( err ) ); goto end; } if( ( err = gcry_sexp_build( &cipher_text_sexp, NULL, "(enc-val(flags oaep)(rsa(a %m)))", cipher_text_mpi ) ) ) { msg_Err( this->p_demux, "could not build S-expression for cipher text: %s", gcry_strerror( err ) ); goto end; } /* decrypt */ if( ( err = gcry_pk_decrypt( &plain_text_sexp, cipher_text_sexp, rsa_key.priv_key ) ) ) { msg_Err( this->p_demux, "error while decrypting RSA encrypted info: %s", gcry_strerror( err ) ); goto end; } /* extract plain-text from S-expression */ if( ! ( tmp_sexp = gcry_sexp_find_token( plain_text_sexp, "value", 0 ) ) ) /* when using padding flags, the decrypted S-expression is of the form * "(value <plaintext>)", where <plaintext> is an MPI */ { msg_Err( this->p_demux, "decrypted text is in an unexpected form; decryption may have failed" ); goto end; } /* we could have used the gcry_sexp_nth_data to get the data directly, * but as that function is newly introduced (libgcrypt v1.6), * we prefer compatibility, even though that means passing the data through an MPI first */ if( ! ( plain_text_mpi = gcry_sexp_nth_mpi( tmp_sexp, 1, GCRYMPI_FMT_USG ) ) ) { msg_Err( this->p_demux, "could not extract MPI from decrypted S-expression" ); goto end; } if( ( err = gcry_mpi_aprint( GCRYMPI_FMT_USG, &ps_plain_text, &length, plain_text_mpi ) ) ) { msg_Err( this->p_demux, "error while extracting plain text from MPI: %s", gcry_strerror( err ) ); goto end; } /* interpret the plaintext data */ switch( length ) { case 138: /* SMPTE DCP */ if( this->extractInfo( ps_plain_text, true ) ) goto end; break; case 134: /* Interop DCP */ if( this->extractInfo( ps_plain_text, false ) ) goto end; break; case -1: msg_Err( this->p_demux, "could not decrypt" ); goto end; default: msg_Err( this->p_demux, "CipherValue field length does not match SMPTE nor Interop standards" ); goto end; } i_ret = VLC_SUCCESS; end: free( ps_cipher_text ); gcry_mpi_release( cipher_text_mpi ); gcry_sexp_release( cipher_text_sexp ); gcry_sexp_release( plain_text_sexp ); gcry_mpi_release( plain_text_mpi ); gcry_sexp_release( tmp_sexp ); gcry_free( ps_plain_text ); return i_ret; }
/* Check against PKCS#1 v1.5 encryption test vectors as found at ftp://ftp.rsa.com/pub/rsalabs/tmp/pkcs1v15crypt-vectors.txt . */ static void check_v15crypt (void) { #include "pkcs1v2-v15c.h" gpg_error_t err; int tno, mno; for (tno = 0; tno < DIM (tbl); tno++) { void *rsa_n, *rsa_e, *rsa_d; size_t rsa_n_len, rsa_e_len, rsa_d_len; gcry_sexp_t sec_key, pub_key; if (verbose > 1) info ("(%s)\n", tbl[tno].desc); rsa_n = data_from_hex (tbl[tno].n, &rsa_n_len); rsa_e = data_from_hex (tbl[tno].e, &rsa_e_len); rsa_d = data_from_hex (tbl[tno].d, &rsa_d_len); err = gcry_sexp_build (&sec_key, NULL, "(private-key (rsa (n %b)(e %b)(d %b)))", (int)rsa_n_len, rsa_n, (int)rsa_e_len, rsa_e, (int)rsa_d_len, rsa_d); if (err) die ("constructing private key failed: %s\n", gpg_strerror (err)); err = gcry_sexp_build (&pub_key, NULL, "(public-key (rsa (n %b)(e %b)))", (int)rsa_n_len, rsa_n, (int)rsa_e_len, rsa_e); if (err) die ("constructing public key failed: %s\n", gpg_strerror (err)); gcry_free (rsa_n); gcry_free (rsa_e); gcry_free (rsa_d); for (mno = 0; mno < DIM (tbl[0].m); mno++) { void *mesg, *seed, *encr; size_t mesg_len, seed_len, encr_len; gcry_sexp_t plain, ciph; if (verbose) info ("running test: %s\n", tbl[tno].m[mno].desc); mesg = data_from_hex (tbl[tno].m[mno].mesg, &mesg_len); seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); err = gcry_sexp_build (&plain, NULL, "(data (flags pkcs1)(hash-algo sha1)" "(value %b)(random-override %b))", (int)mesg_len, mesg, (int)seed_len, seed); if (err) die ("constructing plain data failed: %s\n", gpg_strerror (err)); gcry_free (mesg); gcry_free (seed); err = gcry_pk_encrypt (&ciph, plain, pub_key); if (err) { show_sexp ("plain:\n", ciph); fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); } else { if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, tbl[tno].m[mno].desc)) { show_sexp ("encrypt result:\n", ciph); fail ("mismatch in gcry_pk_encrypt\n"); } gcry_sexp_release (ciph); ciph = NULL; } gcry_sexp_release (plain); plain = NULL; /* Now test the decryption. */ seed = data_from_hex (tbl[tno].m[mno].seed, &seed_len); encr = data_from_hex (tbl[tno].m[mno].encr, &encr_len); err = gcry_sexp_build (&ciph, NULL, "(enc-val (flags pkcs1)(hash-algo sha1)" "(random-override %b)" "(rsa (a %b)))", (int)seed_len, seed, (int)encr_len, encr); if (err) die ("constructing cipher data failed: %s\n", gpg_strerror (err)); gcry_free (encr); gcry_free (seed); err = gcry_pk_decrypt (&plain, ciph, sec_key); if (err) { show_sexp ("ciph:\n", ciph); fail ("gcry_pk_decrypt failed: %s\n", gpg_strerror (err)); } else { if (extract_cmp_data (plain, "value", tbl[tno].m[mno].mesg, tbl[tno].m[mno].desc)) { show_sexp ("decrypt result:\n", plain); fail ("mismatch in gcry_pk_decrypt\n"); } gcry_sexp_release (plain); plain = NULL; } gcry_sexp_release (ciph); ciph = NULL; } gcry_sexp_release (sec_key); gcry_sexp_release (pub_key); } }
static void check_keys_crypt (gcry_sexp_t pkey, gcry_sexp_t skey, gcry_sexp_t plain0, gpg_err_code_t decrypt_fail_code) { gcry_sexp_t plain1, cipher, l; gcry_mpi_t x0, x1; int rc; int have_flags; /* Extract data from plaintext. */ l = gcry_sexp_find_token (plain0, "value", 0); x0 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); /* Encrypt data. */ rc = gcry_pk_encrypt (&cipher, plain0, pkey); if (rc) die ("encryption failed: %s\n", gcry_strerror (rc)); l = gcry_sexp_find_token (cipher, "flags", 0); have_flags = !!l; gcry_sexp_release (l); /* Decrypt data. */ rc = gcry_pk_decrypt (&plain1, cipher, skey); gcry_sexp_release (cipher); if (rc) { if (decrypt_fail_code && gpg_err_code (rc) == decrypt_fail_code) { gcry_mpi_release (x0); return; /* This is the expected failure code. */ } die ("decryption failed: %s\n", gcry_strerror (rc)); } /* Extract decrypted data. Note that for compatibility reasons, the output of gcry_pk_decrypt depends on whether a flags lists (even if empty) occurs in its input data. Because we passed the output of encrypt directly to decrypt, such a flag value won't be there as of today. We check it anyway. */ l = gcry_sexp_find_token (plain1, "value", 0); if (l) { if (!have_flags) die ("compatibility mode of pk_decrypt broken\n"); gcry_sexp_release (plain1); x1 = gcry_sexp_nth_mpi (l, 1, GCRYMPI_FMT_USG); gcry_sexp_release (l); } else { if (have_flags) die ("compatibility mode of pk_decrypt broken\n"); x1 = gcry_sexp_nth_mpi (plain1, 0, GCRYMPI_FMT_USG); gcry_sexp_release (plain1); } /* Compare. */ if (gcry_mpi_cmp (x0, x1)) die ("data corrupted\n"); gcry_mpi_release (x0); gcry_mpi_release (x1); }