int tls_connection_load_cipher(struct SSLConnection *conn) { if (conn->cipher_suite.cs1 != 0x00) return 1; if (conn->cipher_suite.cs2 == TLS_RSA_WITH_AES_256_CBC_SHA.cs2) { conn->ciph = gcry_cipher_map_name("AES256"); } else if (conn->cipher_suite.cs2 == TLS_RSA_WITH_AES_128_CBC_SHA.cs2) { conn->ciph = gcry_cipher_map_name("AES"); } else { return 1; } return 0; }
int init_My_crypto(My_crypto* obj, const char alg[], int mode) { obj->_cipher = gcry_cipher_map_name(alg); //ret->_md = gcry_md_map_name("MD5"); if (gcry_cipher_open(&(obj->_cipherhd), obj->_cipher, mode, 0) != GPG_ERR_NO_ERROR) return -1; return 0; }
static crypto_t _cipher_new(crypto_t c, gchar *key, const gchar *algoname, const gint cipher_mode, const guint cipher_flags) { gcry_error_t e; c->algo = gcry_cipher_map_name(algoname); if (c->algo ==0) { return (_fail(c, g_strdup_printf("algorithm `%s' was not available", algoname))); } c->cipher.flags = cipher_flags; c->cipher.mode = cipher_mode; c->cipher.should_pad = (cipher_mode != GCRY_CIPHER_MODE_STREAM && cipher_mode != GCRY_CIPHER_MODE_CFB && cipher_mode != GCRY_CIPHER_MODE_OFB) ? TRUE : FALSE; c->cipher.blklen = gcry_cipher_get_algo_blklen(c->algo); if (c->cipher.blklen ==0) return (_fail(c, g_strdup("gcry_cipher_get_algo_blklen failed"))); e = gcry_cipher_open(&c->cipher.h, c->algo, cipher_mode, cipher_flags); if (e != 0) { return (_fail(c, g_strdup_printf("gcry_cipher_open failed: %s", gpg_strerror(e)))); } return (_setkey(c, key)); }
static void check_ciphers (void) { static int algos[] = { GCRY_CIPHER_3DES, GCRY_CIPHER_CAST5, GCRY_CIPHER_BLOWFISH, GCRY_CIPHER_AES, GCRY_CIPHER_AES192, GCRY_CIPHER_AES256, GCRY_CIPHER_TWOFISH, GCRY_CIPHER_TWOFISH128, GCRY_CIPHER_DES, GCRY_CIPHER_SERPENT128, GCRY_CIPHER_SERPENT192, GCRY_CIPHER_SERPENT256, 0 }; static int algos2[] = { GCRY_CIPHER_ARCFOUR, 0 }; int i; for (i = 0; algos[i]; i++) { if (verbose) fprintf (stderr, "checking `%s' [%i]\n", gcry_cipher_algo_name (algos[i]), gcry_cipher_map_name (gcry_cipher_algo_name (algos[i]))); check_one_cipher (algos[i], GCRY_CIPHER_MODE_ECB, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CFB, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0); } for (i = 0; algos2[i]; i++) { if (verbose) fprintf (stderr, "checking `%s'\n", gcry_cipher_algo_name (algos2[i])); check_one_cipher (algos2[i], GCRY_CIPHER_MODE_STREAM, 0); } /* we have now run all cipher's selftests */ /* TODO: add some extra encryption to test the higher level functions */ }
/** \brief init the gcry_md_hd * * - this init is assumed to be done everytime it is done for ciph_type */ bool skey_ciph_t::init_gcry_hd() throw() { const skey_ciph_algo_t &algo = ciph_type.get_algo(); // get the algo from the algo_str int gcry_cipher_algo = gcry_cipher_map_name( algo.to_string().c_str() ); // if the algo_str isnt supported, throw an exception if( !gcry_cipher_algo ){ KLOG_ERR("Can't map " << algo.to_string() << " in gcrypt cipher_map_name"); return true; } // open the gcrypt cipher if( gcry_cipher_open(&gcry_cipher_hd, gcry_cipher_algo, get_gcry_cipher_mode(), GCRY_CIPHER_SECURE) ){ KLOG_ERR("Can't open " << ciph_type << " in gcrypt cipher_open"); return true; } // return false if no error occured return false; }
void cipher_bench (char **argv, int argc) { int i, algo; bench_print_section ("cipher", "Cipher"); if (argv && argc) { for (i = 0; i < argc; i++) { algo = gcry_cipher_map_name (argv[i]); if (algo) _cipher_bench (algo); } } else { for (i = 1; i < 400; i++) if (!gcry_cipher_test_algo (i)) _cipher_bench (i); } }
/* Initialize the data encryption key (session key). */ static int init_dek (DEK dek) { int rc=0, mode, i; dek->algo = gcry_cipher_map_name (dek->algoid); mode = gcry_cipher_mode_from_oid (dek->algoid); if (!dek->algo || !mode) { log_error ("unsupported algorithm `%s'\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } /* Extra check for algorithms we consider to be too weak for encryption, although we support them for decryption. Note that there is another check below discriminating on the key length. */ switch (dek->algo) { case GCRY_CIPHER_DES: case GCRY_CIPHER_RFC2268_40: log_error ("cipher algorithm `%s' not allowed: too weak\n", gcry_cipher_algo_name (dek->algo)); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); default: break; } dek->keylen = gcry_cipher_get_algo_keylen (dek->algo); if (!dek->keylen || dek->keylen > sizeof (dek->key)) return gpg_error (GPG_ERR_BUG); dek->ivlen = gcry_cipher_get_algo_blklen (dek->algo); if (!dek->ivlen || dek->ivlen > sizeof (dek->iv)) return gpg_error (GPG_ERR_BUG); /* Make sure we don't use weak keys. */ if (dek->keylen < 100/8) { log_error ("key length of `%s' too small\n", dek->algoid); return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM); } rc = gcry_cipher_open (&dek->chd, dek->algo, mode, GCRY_CIPHER_SECURE); if (rc) { log_error ("failed to create cipher context: %s\n", gpg_strerror (rc)); return rc; } for (i=0; i < 8; i++) { gcry_randomize (dek->key, dek->keylen, GCRY_STRONG_RANDOM ); rc = gcry_cipher_setkey (dek->chd, dek->key, dek->keylen); if (gpg_err_code (rc) != GPG_ERR_WEAK_KEY) break; log_info(_("weak key created - retrying\n") ); } if (rc) { log_error ("failed to set the key: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } gcry_create_nonce (dek->iv, dek->ivlen); rc = gcry_cipher_setiv (dek->chd, dek->iv, dek->ivlen); if (rc) { log_error ("failed to set the IV: %s\n", gpg_strerror (rc)); gcry_cipher_close (dek->chd); dek->chd = NULL; return rc; } return 0; }
/** \brief return the gcrypt algo id */ int skey_ciph_t::get_gcry_cipher_algo() const throw() { const skey_ciph_algo_t &algo = ciph_type.get_algo(); int gcry_cipher_algo= gcry_cipher_map_name( algo.to_string().c_str() ); return gcry_cipher_algo; }
static void cipher_bench ( const char *algoname ) { static int header_printed; int algo; gcry_cipher_hd_t hd; int i; int keylen, blklen; char key[128]; char *outbuf, *buf; char *raw_outbuf, *raw_buf; size_t allocated_buflen, buflen; int repetitions; static struct { int mode; const char *name; int blocked; } modes[] = { { GCRY_CIPHER_MODE_ECB, " ECB/Stream", 1 }, { GCRY_CIPHER_MODE_CBC, " CBC", 1 }, { GCRY_CIPHER_MODE_CFB, " CFB", 0 }, { GCRY_CIPHER_MODE_OFB, " OFB", 0 }, { GCRY_CIPHER_MODE_CTR, " CTR", 0 }, { GCRY_CIPHER_MODE_STREAM, "", 0 }, {0} }; int modeidx; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_cipher_test_algo (i) ) cipher_bench (gcry_cipher_algo_name (i)); return; } if (large_buffers) { allocated_buflen = 1024 * 100; repetitions = 10; } else { allocated_buflen = 1024; repetitions = 1000; } repetitions *= cipher_repetitions; raw_buf = gcry_xmalloc (allocated_buflen+15); buf = (raw_buf + ((16 - ((size_t)raw_buf & 0x0f)) % buffer_alignment)); outbuf = raw_outbuf = gcry_xmalloc (allocated_buflen+15); outbuf = (raw_outbuf + ((16 - ((size_t)raw_outbuf & 0x0f)) % buffer_alignment)); if (!header_printed) { if (cipher_repetitions != 1) printf ("Running each test %d times.\n", cipher_repetitions); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" %-15s", modes[modeidx].name ); putchar ('\n'); printf ("%-12s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) if (*modes[modeidx].name) printf (" ---------------" ); putchar ('\n'); header_printed = 1; } algo = gcry_cipher_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); exit (1); } keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", algoname); exit (1); } if ( keylen > sizeof key ) { fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", algo, keylen ); exit (1); } for (i=0; i < keylen; i++) key[i] = i + (clock () & 0xff); blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) { fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", algoname); exit (1); } printf ("%-12s", gcry_cipher_algo_name (algo)); fflush (stdout); for (modeidx=0; modes[modeidx].mode; modeidx++) { if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM) | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM)) continue; for (i=0; i < sizeof buf; i++) buf[i] = i; err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } buflen = allocated_buflen; if (modes[modeidx].blocked) buflen = (buflen / blklen) * blklen; start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", gpg_strerror (err) ); exit (1); } err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); exit (1); } if (!cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } start_timer (); for (i=err=0; !err && i < repetitions; i++) { if (cipher_with_keysetup) { err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } } err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen); } stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", gpg_strerror (err) ); exit (1); } } putchar ('\n'); gcry_free (raw_buf); gcry_free (raw_outbuf); }
static void cipher_bench ( const char *algoname ) { static int header_printed; int algo; gcry_cipher_hd_t hd; int i; int keylen, blklen; char key[128]; char outbuf[1000], buf[1000]; size_t buflen; static struct { int mode; const char *name; int blocked; } modes[] = { { GCRY_CIPHER_MODE_ECB, "ECB", 1 }, { GCRY_CIPHER_MODE_CBC, "CBC", 1 }, { GCRY_CIPHER_MODE_CFB, "CFB", 0 }, { GCRY_CIPHER_MODE_CTR, "CTR", 0 }, { GCRY_CIPHER_MODE_STREAM, "STREAM", 0 }, {0} }; int modeidx; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_cipher_test_algo (i) ) cipher_bench (gcry_cipher_algo_name (i)); return; } if (!header_printed) { printf ("%-10s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) printf (" %-15s", modes[modeidx].name ); putchar ('\n'); printf ("%-10s", ""); for (modeidx=0; modes[modeidx].mode; modeidx++) printf (" ---------------" ); putchar ('\n'); header_printed = 1; } algo = gcry_cipher_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid cipher algorithm `%s'\n", algoname); exit (1); } keylen = gcry_cipher_get_algo_keylen (algo); if (!keylen) { fprintf (stderr, PGM ": failed to get key length for algorithm `%s'\n", algoname); exit (1); } if ( keylen > sizeof key ) { fprintf (stderr, PGM ": algo %d, keylength problem (%d)\n", algo, keylen ); exit (1); } for (i=0; i < keylen; i++) key[i] = i + (clock () & 0xff); blklen = gcry_cipher_get_algo_blklen (algo); if (!blklen) { fprintf (stderr, PGM ": failed to get block length for algorithm `%s'\n", algoname); exit (1); } printf ("%-10s", gcry_cipher_algo_name (algo)); fflush (stdout); for (modeidx=0; modes[modeidx].mode; modeidx++) { if ((blklen > 1 && modes[modeidx].mode == GCRY_CIPHER_MODE_STREAM) | (blklen == 1 && modes[modeidx].mode != GCRY_CIPHER_MODE_STREAM)) { printf (" " ); continue; } for (i=0; i < sizeof buf; i++) buf[i] = i; err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'\n", algoname); exit (1); } err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } buflen = sizeof buf; if (modes[modeidx].blocked) buflen = (buflen / blklen) * blklen; start_timer (); for (i=err=0; !err && i < 1000; i++) err = gcry_cipher_encrypt ( hd, outbuf, buflen, buf, buflen); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_encrypt failed: %s\n", gpg_strerror (err) ); exit (1); } err = gcry_cipher_open (&hd, algo, modes[modeidx].mode, 0); if (err) { fprintf (stderr, PGM ": error opening cipher `%s'/n", algoname); exit (1); } err = gcry_cipher_setkey (hd, key, keylen); if (err) { fprintf (stderr, "gcry_cipher_setkey failed: %s\n", gpg_strerror (err)); gcry_cipher_close (hd); exit (1); } start_timer (); for (i=err=0; !err && i < 1000; i++) err = gcry_cipher_decrypt ( hd, outbuf, buflen, buf, buflen); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_cipher_close (hd); if (err) { fprintf (stderr, "gcry_cipher_decrypt failed: %s\n", gpg_strerror (err) ); exit (1); } } putchar ('\n'); }
static gcry_cipher_hd_t prepare_and_encode_pkcs8_cipher (GNode *asn, const gchar *password, gsize n_password, gsize *n_block) { GNode *asn1_params = NULL; gcry_cipher_hd_t cih; guchar *salt; gsize n_salt; gcry_error_t gcry; guchar *key, *iv; gsize n_key; int iterations; init_quarks (); /* Make sure the encryption algorithm works */ g_return_val_if_fail (gcry_cipher_algo_info (gcry_cipher_map_name (g_quark_to_string (OID_PKCS12_PBE_3DES_SHA1)), GCRYCTL_TEST_ALGO, NULL, 0) == 0, NULL); /* The encryption algorithm */ if(!egg_asn1x_set_oid_as_quark (egg_asn1x_node (asn, "encryptionAlgorithm", "algorithm", NULL), OID_PKCS12_PBE_3DES_SHA1)) g_return_val_if_reached (NULL); /* Randomize some input for the password based secret */ iterations = g_random_int_range (1000, 4096); n_salt = 8; salt = g_malloc (n_salt); gcry_create_nonce (salt, n_salt); /* Allocate space for the key and iv */ n_key = gcry_cipher_get_algo_keylen (GCRY_CIPHER_3DES); *n_block = gcry_cipher_get_algo_blklen (GCRY_MD_SHA1); g_return_val_if_fail (n_key && *n_block, NULL); if (!egg_symkey_generate_pkcs12 (GCRY_CIPHER_3DES, GCRY_MD_SHA1, password, n_password, salt, sizeof (salt), iterations, &key, &iv)) g_return_val_if_reached (NULL); /* Now write out the parameters */ asn1_params = egg_asn1x_create (pkix_asn1_tab, "pkcs-12-PbeParams"); g_return_val_if_fail (asn1_params, NULL); egg_asn1x_set_string_as_raw (egg_asn1x_node (asn1_params, "salt", NULL), salt, n_salt, g_free); egg_asn1x_set_integer_as_ulong (egg_asn1x_node (asn1_params, "iterations", NULL), iterations); egg_asn1x_set_any_from (egg_asn1x_node (asn, "encryptionAlgorithm", "parameters", NULL), asn1_params); /* Now make a cipher that matches what we wrote out */ gcry = gcry_cipher_open (&cih, GCRY_CIPHER_3DES, GCRY_CIPHER_MODE_CBC, 0); g_return_val_if_fail (gcry == 0, NULL); g_return_val_if_fail (cih, NULL); gcry_cipher_setiv (cih, iv, *n_block); gcry_cipher_setkey (cih, key, n_key); g_free (iv); egg_secure_free (key); egg_asn1x_destroy (asn1_params); return cih; }
int main (int argc, char **argv) { /* Parse arguments */ if(opt_parse("usage: %s < filename > [options]", options, argv) == 0) { opt_help(0, NULL); } /* Read in password */ char *pass = NULL; size_t passLen = 0; ssize_t passRead; char *fileName; printf("Password: "******"libgcrypt version mismatch\n", stderr); exit (2); } gcry_control(GCRYCTL_SUSPEND_SECMEM_WARN); gcry_control(GCRYCTL_INIT_SECMEM, 131072, 0); gcry_control(GCRYCTL_RESUME_SECMEM_WARN); gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); /* Key Generation */ char key[16] = ""; size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER); const char *salt = "NaCl"; size_t saltLen = sizeof(salt); unsigned long iterations = 4096; gpg_error_t errStatus; errStatus = gcry_kdf_derive(pass, passLen, GCRY_KDF_PBKDF2, GCRY_MD_SHA512, salt, saltLen, iterations, keyLength, key); /* Cipher Setup */ // printf("Key: %X\n", key); puts(key); const char* IV = "5844"; // const int IV = 5844; const char *name = "aes128"; int algorithm = gcry_cipher_map_name(name); size_t blockLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER); gcry_cipher_hd_t hand; gcry_cipher_open(&hand, algorithm, GCRY_CIPHER_MODE_CBC, 0); gcry_cipher_setkey(hand, key, keyLength); gcry_cipher_setiv(hand, IV, blockLength); char *buffer; long len; size_t macLen = 0; /* If the local flag is set then we encrypt the file locally instead of sending it over the network Otherwise we send the file over the network */ if (local == 1) { /* Open the file for reading and then copy to a buffer */ FILE *ifp = fopen(argv[1], "rb"); if(ifp == 0) { printf("%s", "Could not open file"); return 1; } // Lets figure out how big the file is fseek(ifp, 0L, SEEK_END); len = ftell(ifp); rewind(ifp); // Allocate secure RAM for the buffer buffer = gcry_calloc_secure(len, sizeof(char)); // Copy the input file to the buffer fread(buffer, 1, len, ifp); // Since we're running locally, the name of the output file is the same as the argument // without the .gt fileName = argv[1]; size_t inLen = strlen(fileName); // End the filename by replacing the "." with a NULL char fileName[inLen-3] = '\0'; fclose(ifp); } else { /* Retrieve file from remote computer Open a socket and listen for communication */ int sock; int localSock; struct sockaddr_in inPort; inPort.sin_family = AF_INET; inPort.sin_addr.s_addr = INADDR_ANY; inPort.sin_port = htons(port); sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == -1) { printf("%s", "Could not open socket"); exit(1); } bind(sock, (struct sockaddr *) &inPort, sizeof(inPort)); listen(sock, 0); printf("%s", "Waiting for connection...\n"); // Accepting the connection localSock = accept(sock, NULL, NULL); printf("%s", "Inbound file...\n"); // Allocate some memory for the buffer // len+(160(len%16)) is so that the memory we allocate is divisible // by the blocklength, which is 16 len = 4096L; buffer = gcry_calloc_secure(len+(16-(len%16)), sizeof(char)); long dataRead = 0L; int keepReading = 1; // Let's figure out how much data we're getting // If I were to do this part over, I would instead open two connections // from techrypt- where the first connection sends the // amount of data to be transmitted in the second connection while (keepReading) { dataRead = recv(localSock, buffer, len, MSG_PEEK); if (dataRead == len) { len = len * 2; sleep(.5); buffer = gcry_realloc(buffer, len); keepReading = 1; } else { keepReading = 0; } } // How much data did we read? len = dataRead; // Now lets actually store it in the buffer dataRead = recv(localSock, buffer, len, 0); // Output file name is the command line argument fileName = argv[1]; close(sock); /* Setup the HMAC */ gcry_md_hd_t macHand; macLen = gcry_md_get_algo_dlen(GCRY_MD_SHA512); char *mac = gcry_calloc_secure(macLen, sizeof(char)); gcry_md_open(&macHand, GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC); gcry_md_setkey(macHand, key, keyLength); // Generate the HMAC for the message we received // Since we know there's a MAC of size macLen at the end // we will only generate the hash based on the first // len-macLen bytes gcry_md_write(macHand, buffer, len-macLen); mac = gcry_md_read(macHand, 0); /* Strip HMAC from buffer */ char *exMac = buffer+(len-macLen); /* Check HMAC against our HMAC */ // I think this may be exploitable with a strategically placed NULL // The use of memcmp could fix this...if I have time I will replace and check if(strncmp(mac, exMac, macLen) != 0) { exit(62); } } /* Decrypt the buffer */ gcry_cipher_decrypt(hand, buffer, len, NULL, 0); /* Reverse padding algorithm Strip the amount of bytes from the end of the file determined by the contents of the last byte This is why using PKCS7 was so useful */ char *padPtr = buffer+len-macLen-1; int writeLen = len-macLen-(*padPtr); /* Write the buffer to a file */ FILE *ofp = fopen(fileName, "wb"); fwrite(buffer, 1, writeLen, ofp); fclose(ofp); return 0; }