int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk) { unsigned char key[EVP_MAX_KEY_LENGTH]; int ret = -1; int i, j, max = 0; char *s = NULL; /* * Make sure ctx is properly initialized so that we can always pass * it to PEM_ENCODE_SEAL_CTX_cleanup() in the error path. */ EVP_EncodeInit(&ctx->encode); EVP_MD_CTX_init(&ctx->md); EVP_CIPHER_CTX_init(&ctx->cipher); for (i = 0; i < npubk; i++) { if (pubk[i]->type != EVP_PKEY_RSA) { PEMerror(PEM_R_PUBLIC_KEY_NO_RSA); goto err; } j = RSA_size(pubk[i]->pkey.rsa); if (j > max) max = j; } s = reallocarray(NULL, max, 2); if (s == NULL) { PEMerror(ERR_R_MALLOC_FAILURE); goto err; } if (!EVP_SignInit(&ctx->md, md_type)) goto err; ret = EVP_SealInit(&ctx->cipher, type, ek, ekl, iv, pubk, npubk); if (ret <= 0) goto err; /* base64 encode the keys */ for (i = 0; i < npubk; i++) { j = EVP_EncodeBlock((unsigned char *)s, ek[i], RSA_size(pubk[i]->pkey.rsa)); ekl[i] = j; memcpy(ek[i], s, j + 1); } ret = npubk; if (0) { err: PEM_ENCODE_SEAL_CTX_cleanup(ctx); } free(s); explicit_bzero(key, sizeof(key)); return (ret); }
void openssl_evp_asycrypt() { RSA *rkey; BIGNUM *bne; EVP_PKEY *pubkey[2]; EVP_CIPHER_CTX ctx1, ctx2; int i, ekl[2], len1 = 0, len2 = 0, len3 = 0; unsigned char ins[] = "openssl asymmetric encrypt test"; unsigned char iv[8], pen[MAX1_LEN], *ek[2], sde[MAX1_LEN]; ek[0] = (unsigned char *)malloc(MAX1_LEN); ek[1] = (unsigned char *)malloc(MAX1_LEN); memset(pen, 0, MAX1_LEN); memset(sde, 0, MAX1_LEN); memset(ek[0], 0, MAX1_LEN); memset(ek[1], 0, MAX1_LEN); bne = BN_new(); BN_set_word(bne, RSA_3); rkey = RSA_new(); RSA_generate_key_ex(rkey, MAX1_LEN, bne, NULL); pubkey[0] = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pubkey[0], rkey); EVP_CIPHER_CTX_init(&ctx1); EVP_SealInit(&ctx1, EVP_des_ede3_cbc(), ek, ekl, iv, pubkey, 1); EVP_SealUpdate(&ctx1, pen, &len1, ins, strlen((char *)ins)); EVP_SealFinal(&ctx1, pen + len1, &len3); len1 += len3; printf("\nEVP_ASYEncry(%s) = ", ins); for (i = 0; i < len1; i++) printf("0x%.02x ", pen[i]); printf("\n"); EVP_CIPHER_CTX_cleanup(&ctx1); len3 = 0; EVP_CIPHER_CTX_init(&ctx2); EVP_OpenInit(&ctx2, EVP_des_ede3_cbc(), ek[0], ekl[0], iv, pubkey[0]); EVP_OpenUpdate(&ctx2, sde, &len2, pen, len1); EVP_OpenFinal(&ctx2, sde + len2, &len3); len2 += len3; printf("EVP_ASYDecry("); for (i = 0; i < len1; i++) printf("0x%.02x ", pen[i]); printf(") = %s\n", sde); EVP_CIPHER_CTX_cleanup(&ctx2); free(ek[0]); free(ek[1]); EVP_PKEY_free(pubkey[0]); BN_free(bne); }
int PEM_SealInit(PEM_ENCODE_SEAL_CTX *ctx, EVP_CIPHER *type, EVP_MD *md_type, unsigned char **ek, int *ekl, unsigned char *iv, EVP_PKEY **pubk, int npubk) { unsigned char key[EVP_MAX_KEY_LENGTH]; int ret = -1; int i, j, max = 0; char *s = NULL; for (i = 0; i < npubk; i++) { if (pubk[i]->type != EVP_PKEY_RSA) { PEMerr(PEM_F_PEM_SEALINIT, PEM_R_PUBLIC_KEY_NO_RSA); goto err; } j = RSA_size(pubk[i]->pkey.rsa); if (j > max) max = j; } s = (char *)reallocarray(NULL, max, 2); if (s == NULL) { PEMerr(PEM_F_PEM_SEALINIT, ERR_R_MALLOC_FAILURE); goto err; } EVP_EncodeInit(&ctx->encode); EVP_MD_CTX_init(&ctx->md); if (!EVP_SignInit(&ctx->md, md_type)) goto err; EVP_CIPHER_CTX_init(&ctx->cipher); ret = EVP_SealInit(&ctx->cipher, type, ek, ekl, iv, pubk, npubk); if (ret <= 0) goto err; /* base64 encode the keys */ for (i = 0; i < npubk; i++) { j = EVP_EncodeBlock((unsigned char *)s, ek[i], RSA_size(pubk[i]->pkey.rsa)); ekl[i] = j; memcpy(ek[i], s, j + 1); } ret = npubk; err: if (s != NULL) free(s); OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH); return (ret); }
/// 计算数字信封,得到加密密钥和初始向量 int do_seal(const EVP_CIPHER * cipher, unsigned char * pbuf,int plen, unsigned char * ebuf,int * elen, unsigned char * iv, unsigned char *kbuf,int* klen) { EVP_CIPHER_CTX ectx; EVP_PKEY *pub_key[1]; unsigned char *ekey[1]; int tmp_len = 0; int ret = 0; RAND_seed("gt alarm system",10); pub_key[0] = NULL; ekey[0] = kbuf; if(!g_pub_key) return ERR_ENV_CERT_INVALID; EVP_CIPHER_CTX_init(&ectx);//TaoNote: 如果不调用EVP_CIPHER_CTX_init,不影响运算,但有内存泄漏 do{ pub_key[0] = g_pub_key; if(1 != EVP_SealInit(&ectx,cipher,ekey,klen,iv,pub_key,1)) { ret = ERR_ENV_ENCRYPT_FAILED; break; } *elen = 0; if(1 != EVP_SealUpdate(&ectx, ebuf+*elen,elen,pbuf,plen)) { ret = ERR_ENV_ENCRYPT_FAILED; break; } if(1 != EVP_SealFinal(&ectx, ebuf + *elen,&tmp_len)) { ret = ERR_ENV_ENCRYPT_FAILED; break; } *elen = *elen + tmp_len; }while(0); EVP_CIPHER_CTX_cleanup(&ectx); return ret; }
void openssl_evp_rsacripher() { RSA *rkey; BIGNUM *bne; EVP_PKEY *pubkey[2]; const EVP_CIPHER *type; EVP_CIPHER_CTX ctx1, ctx2; int i, ekl[2], total = 0, len1 = 0, len2 = 0; const unsigned char ins[COMM_LEN] = "openssl evp"; unsigned char outs[LINE_LEN], iv[8], *ek[2], de[LINE_LEN]; bne = BN_new(); BN_set_word(bne, RSA_3); rkey = RSA_new(); RSA_generate_key_ex(rkey, MAX1_LEN, bne, NULL); pubkey[0] = EVP_PKEY_new(); EVP_PKEY_assign_RSA(pubkey[0], rkey); type = EVP_des_cbc(); ek[0] = malloc(LINE_LEN); ek[1] = malloc(LINE_LEN); EVP_CIPHER_CTX_init(&ctx1); EVP_SealInit(&ctx1, type, ek, ekl, iv, pubkey, 1); EVP_SealUpdate(&ctx1, outs, &total, ins, 11); EVP_SealFinal(&ctx1, outs + total, &len1); total += len1; printf("\nEVP_RSASEAL(%s) = ", ins); for (i = 0; i < total; i++) printf("0x%.02x ", outs[i]); EVP_CIPHER_CTX_cleanup(&ctx1); memset(de, 0, LINE_LEN); EVP_CIPHER_CTX_init(&ctx2); EVP_OpenInit(&ctx2, EVP_des_cbc(), ek[0], ekl[0], iv, pubkey[0]); EVP_OpenUpdate(&ctx2, de, &len2, outs, total); EVP_OpenFinal(&ctx2, de + len2, &len1); len2 += len1; printf("= %s\n", de); EVP_CIPHER_CTX_cleanup(&ctx2); free(ek[0]); free(ek[1]); EVP_PKEY_free(pubkey[0]); BN_free(bne); }
static int test_EVP_Enveloped(void) { int ret = 0; EVP_CIPHER_CTX *ctx = NULL; EVP_PKEY *keypair = NULL; unsigned char *kek = NULL; unsigned char iv[EVP_MAX_IV_LENGTH]; static const unsigned char msg[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; int len, kek_len, ciphertext_len, plaintext_len; unsigned char ciphertext[32], plaintext[16]; const EVP_CIPHER *type = EVP_aes_256_cbc(); if (!TEST_ptr(keypair = load_example_rsa_key()) || !TEST_ptr(kek = OPENSSL_zalloc(EVP_PKEY_size(keypair))) || !TEST_ptr(ctx = EVP_CIPHER_CTX_new()) || !TEST_true(EVP_SealInit(ctx, type, &kek, &kek_len, iv, &keypair, 1)) || !TEST_true(EVP_SealUpdate(ctx, ciphertext, &ciphertext_len, msg, sizeof(msg))) || !TEST_true(EVP_SealFinal(ctx, ciphertext + ciphertext_len, &len))) goto err; ciphertext_len += len; if (!TEST_true(EVP_OpenInit(ctx, type, kek, kek_len, iv, keypair)) || !TEST_true(EVP_OpenUpdate(ctx, plaintext, &plaintext_len, ciphertext, ciphertext_len)) || !TEST_true(EVP_OpenFinal(ctx, plaintext + plaintext_len, &len))) goto err; plaintext_len += len; if (!TEST_mem_eq(msg, sizeof(msg), plaintext, plaintext_len)) goto err; ret = 1; err: OPENSSL_free(kek); EVP_PKEY_free(keypair); EVP_CIPHER_CTX_free(ctx); return ret; }
bool OTEnvelope::Seal(const OTAsymmetricKey & RecipPubKey, const OTString & theContents) { bool retval = false; EVP_CIPHER_CTX ctx; unsigned char buffer[4096]; unsigned char buffer_out[4096 + EVP_MAX_IV_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; size_t len = 0; int len_out = 0; unsigned char * ek = NULL; int eklen = 0; uint32_t eklen_n = 0; memset(buffer, 0, 4096); memset(buffer_out, 0, 4096 + EVP_MAX_IV_LENGTH); memset(iv, 0, EVP_MAX_IV_LENGTH); OTAsymmetricKey & publicKey = (OTAsymmetricKey &)RecipPubKey; EVP_PKEY * pkey = (EVP_PKEY *)publicKey.GetKey(); if (NULL == pkey) { OTLog::Error("Null public key in OTEnvelope::Seal\n"); return false; } // This is where the envelope final contents will be placed. m_dataContents.Release(); EVP_CIPHER_CTX_init(&ctx); ek = (unsigned char*)malloc(EVP_PKEY_size(pkey)); OT_ASSERT(NULL != ek); memset(ek, 0, EVP_PKEY_size(pkey)); if (!EVP_SealInit(&ctx, EVP_aes_128_cbc(), &ek, &eklen, iv, &pkey, 1)) { OTLog::Error("EVP_SealInit: failed.\n"); free(ek); ek = NULL; return false; } // First we write out the encrypted key length, then the encrypted key, // then the iv (the IV length is fixed by the cipher we have chosen). eklen_n = htonl(eklen); OTData dataEKSize(&eklen_n, sizeof(eklen_n)); // Encrypted Key size. (EK). Bytes are in network order. OTData dataEK(ek, eklen); // Encrypted Key OTData dataIV(iv, EVP_CIPHER_iv_length(EVP_aes_128_cbc())); // Initialization Vector // Concatenate (to the envelope result buffer) the three pieces of final data we have so far. m_dataContents += dataEKSize; m_dataContents += dataEK; m_dataContents += dataIV; // Next we put the plaintext into a data object so we can process it. OTData plaintext((const void*)theContents.Get(), theContents.GetLength()+1); // +1 for null terminator // Now we process the input and write the encrypted data to the // output. while (0 < (len = plaintext.OTfread((char*)buffer, sizeof(buffer)))) { if (!EVP_SealUpdate(&ctx, buffer_out, &len_out, buffer, len)) { OTLog::Error("EVP_SealUpdate: failed.\n"); free(ek); ek = NULL; return false; } OTData dataSealUpdate(buffer_out, len_out); m_dataContents += dataSealUpdate; } if (!EVP_SealFinal(&ctx, buffer_out, &len_out)) { OTLog::Error("EVP_SealFinal: failed.\n"); free(ek); ek = NULL; return false; } OTData dataSealFinal(buffer_out, len_out); m_dataContents += dataSealFinal; retval = true; free(ek); ek = NULL; return retval; }
void main_encrypt(void) { unsigned int ebuflen; EVP_CIPHER_CTX ectx; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *ekey[1]; int readlen; int ekeylen, net_ekeylen; EVP_PKEY *pubKey[1]; char buf[512]; char ebuf[512]; memset(iv, '\0', sizeof(iv)); pubKey[0] = ReadPublicKey(PUBFILE); if(!pubKey) { fprintf(stderr,"Error: can't load public key"); exit(1); } ekey[0] = malloc(EVP_PKEY_size(pubKey[0])); if (!ekey[0]) { EVP_PKEY_free(pubKey[0]); perror("malloc"); exit(1); } EVP_SealInit(&ectx, EVP_des_ede3_cbc(), ekey, &ekeylen, iv, pubKey, 1); net_ekeylen = htonl(ekeylen); write(STDOUT, (char*)&net_ekeylen, sizeof(net_ekeylen)); write(STDOUT, ekey[0], ekeylen); write(STDOUT, iv, sizeof(iv)); while(1) { readlen = read(STDIN, buf, sizeof(buf)); if (readlen <= 0) { if (readlen < 0) perror("read"); break; } EVP_SealUpdate(&ectx, ebuf, &ebuflen, buf, readlen); write(STDOUT, ebuf, ebuflen); } EVP_SealFinal(&ectx, ebuf, &ebuflen); write(STDOUT, ebuf, ebuflen); EVP_PKEY_free(pubKey[0]); free(ekey[0]); }
uint8_t* encrypt(const char* keypath, const uint8_t* p, const size_t plen, size_t* clen, uint8_t** iv, size_t* ivlen, uint8_t** ek, size_t* ekl){ // Context and key FILE* ckeyfh; EVP_PKEY *ckey=NULL; // Return codes and errors unsigned long encerr; /* The buffer with the ciphertext */ uint8_t* c; /* Variables related to the symmetric enc of the envelope */ EVP_CIPHER_CTX *encctx = NULL; const EVP_CIPHER* type = EVP_aes_256_cbc(); // Type of encryption int outl, outf; int eklint; /* * Open a public key for encryption */ ckeyfh = fopen(keypath,"r"); if (!ckeyfh) { fprintf(stderr, "%s: Cannot open key file\n", __func__); c = NULL; goto exit_encrypt; } ckey = PEM_read_PUBKEY(ckeyfh, &ckey, NULL, NULL); if (!ckey){ fprintf(stderr,"Cannot read encryption key from file %s\n", keypath); fclose(ckeyfh); c = NULL; goto exit_encrypt; } /* EVP_Seal* need a CIPHER_CTX */ encctx = malloc(sizeof(EVP_CIPHER_CTX)); if (encctx == NULL) { fprintf(stderr, "%s: Out of memory\n", __func__); fclose(ckeyfh); EVP_PKEY_free(ckey); c = NULL; goto exit_encrypt; } EVP_CIPHER_CTX_init(encctx); if (!encctx){ fprintf(stderr,"Cannot inizialize an encryption context\n"); c = NULL; goto cleanup_encrypt; } /* Start the encryption process - generate IV and key */ *ivlen = EVP_CIPHER_iv_length(type); *iv = malloc(*ivlen); if (iv == NULL) { fprintf(stderr, "%s: Out of memory allocating of IV\n", __func__); c = NULL; goto cleanup_encrypt; } *ek = malloc(EVP_PKEY_size(ckey)); if (*ek == NULL) { fprintf(stderr, "%s: Out of memory allocating ek\n", __func__); free(iv); c = NULL; goto cleanup_encrypt; } c = malloc(plen + EVP_CIPHER_block_size(type)); if (c == NULL) { fprintf(stderr, "%s: Out of memory for \n", __func__); free(iv); free(*ek); goto cleanup_encrypt; } if (EVP_SealInit(encctx, type, ek, &eklint, *iv, &ckey, 1) != 1){ ERR_load_crypto_strings(); encerr = ERR_get_error(); fprintf(stderr,"Encrypt failed\n"); printf("%s\n", ERR_error_string(encerr, NULL)); ERR_free_strings(); free(iv); free(*ek); free(c); c = NULL; goto cleanup_encrypt; } *ekl = eklint; /* Encrypt data, then finalize */ if (EVP_SealUpdate(encctx, c, &outl, p, plen) != 1){ ERR_load_crypto_strings(); encerr = ERR_get_error(); fprintf(stderr,"Encrypt failed\n"); printf("%s\n", ERR_error_string(encerr, NULL)); ERR_free_strings(); free(iv); free(*ek); free(c); c = NULL; goto cleanup_encrypt; } if (EVP_SealFinal(encctx, &c[outl], &outf) != 1){ ERR_load_crypto_strings(); encerr = ERR_get_error(); fprintf(stderr,"Encrypt failed\n"); printf("%s\n", ERR_error_string(encerr, NULL)); ERR_free_strings(); free(c); c = NULL; outl = outf = 0; } *clen = outl + outf; cleanup_encrypt: EVP_CIPHER_CTX_cleanup(encctx); free(encctx); fclose(ckeyfh); EVP_PKEY_free(ckey); exit_encrypt: return c; }
unsigned char *rsa_encrypt(unsigned char *plaintext, int *len) { EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init(&ctx); EVP_PKEY *pkey; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *encrypted_key; int encrypted_key_length; uint32_t eklen_n; // Load pem file pkey = load_pubkey("public.pem"); encrypted_key = malloc(EVP_PKEY_size(pkey)); encrypted_key_length = EVP_PKEY_size(pkey); if (!EVP_SealInit(&ctx, EVP_des_ede_cbc(), &encrypted_key, &encrypted_key_length, iv, &pkey, 1)) { fprintf(stderr, "EVP_SealInit: failed.\n"); goto out_free; } eklen_n = htonl(encrypted_key_length); int size_header = sizeof(eklen_n) + encrypted_key_length + EVP_CIPHER_iv_length(EVP_des_ede_cbc()); /* max ciphertext len, see man EVP_CIPHER */ int cipher_len = *len + EVP_CIPHER_CTX_block_size(&ctx) - 1; // header(contains iv, encreypted key and encreypted key length) + data unsigned char *ciphertext = (unsigned char *)malloc(size_header + cipher_len); /* First we write out the encrypted key length, then the encrypted key, * then the iv (the IV length is fixed by the cipher we have chosen). */ int pos = 0; memcpy(ciphertext + pos, &eklen_n, sizeof(eklen_n)); pos += sizeof(eklen_n); memcpy(ciphertext + pos, encrypted_key, encrypted_key_length); pos += encrypted_key_length; memcpy(ciphertext + pos, iv, EVP_CIPHER_iv_length(EVP_des_ede_cbc())); pos += EVP_CIPHER_iv_length(EVP_des_ede_cbc()); /* Now we process the plaintext data and write the encrypted data to the * ciphertext. cipher_len is filled with the length of ciphertext * generated, len is the size of plaintext in bytes * Also we have our updated position, we can skip the header via * ciphertext + pos */ if (!EVP_SealUpdate(&ctx, ciphertext + pos, &cipher_len, plaintext, *len)) { fprintf(stderr, "EVP_SealUpdate: failed.\n"); goto out_free; } /* update ciphertext with the final remaining bytes */ if (!EVP_SealFinal(&ctx, ciphertext + pos + cipher_len, &cipher_len)) { fprintf(stderr, "EVP_SealFinal: failed.\n"); goto out_free; } out_free: EVP_PKEY_free(pkey); free(encrypted_key); EVP_CIPHER_CTX_cleanup(&ctx); return ciphertext; }
int main(int argc, char * argv[]) { unsigned char st[BUFFER_SIZE]; // sifrovany text unsigned char * key; // klic pro sifrovani unsigned char iv[EVP_MAX_IV_LENGTH]; // inicializacni vektor unsigned char readBuffer[BUFFER_SIZE]; const char * filename = argv[1]; const char * outfilename = argv[3]; const char * keyfile = argv[2]; if(argc != 4){ fprintf(stderr, "Error shoud be: pem soubor_s_daty soubor_s_verejnym_klicem vystupni_soubor \n" ); exit(1); } int stLength = 0; int tmpLength = 0; int readlen = 0; int keyLength = 0; FILE * fplainin = fopen(filename,"rb"); FILE * fcyphedout = fopen(outfilename,"w+b"); EVP_PKEY * pubkey; EVP_CIPHER_CTX ctx; FILE * fpubkey = fopen(keyfile,"rb"); pubkey = PEM_read_PUBKEY(fpubkey, NULL, NULL, NULL); //No password protection of the key itself fclose(fpubkey); // printf("Reading pubkey\n"); //EVP_PKEY_CTX * ctx = EVP_PKEY_CTX_new(pubkey,NULL); keyLength = EVP_PKEY_size(pubkey); key = (unsigned char*) malloc(keyLength); EVP_SealInit(&ctx, EVP_des_cbc(), &key, &keyLength, iv, &pubkey, 1); /* printf("Key length: %d\n",keyLength); for(int i=0 ; i < keyLength ; i++){ printf("%x",key[i]); } printf("\n"); */ // printf("Seal Init\n"); int nid = EVP_CIPHER_CTX_nid(&ctx); fwrite(&nid,sizeof(nid),1,fcyphedout); writeData(fcyphedout,(void*)iv,EVP_MAX_IV_LENGTH); fwrite(&keyLength,sizeof(keyLength),1,fcyphedout); writeData(fcyphedout,(void*)key,keyLength); printf("NID: %d\n",nid); while((readlen =fread(readBuffer,1,BUFFER_SIZE,fplainin))!=0){ EVP_SealUpdate(&ctx, st,&stLength, readBuffer, readlen); fwrite(st,1,stLength,fcyphedout); // printf("Seal update\n"); } EVP_SealFinal(&ctx, st, &tmpLength); //printf("Seal final\n"); fwrite(st,1,tmpLength,fcyphedout); fclose(fplainin); fclose(fcyphedout); /* Encrypting end */ //EVP_CIPHER_CTX ctx; free(key); }
/* * RSA public cryptography function. * Encrypt 'in_len' bytes from 'plaintext' buffer with the public key contained in 'pub_key_file' * Parameter 'outlen' is the size of output buffer * It returns the envelope which has to be sent to the receiver or NULL if an error occurs. */ unsigned char* asym_crypto(unsigned char* plaintext, int in_len, int* out_len, char* pub_key_file){ EVP_PKEY* pubkey; int ret; EVP_CIPHER_CTX* ctx; unsigned char* encrypted_key; int encrypted_key_len; unsigned char* iv; int iv_len; unsigned char* ciphertext; int cipher_len; int app; unsigned char* output; int total_output_size = 0; if(plaintext == NULL || in_len < 0 || out_len == NULL || pub_key_file == NULL) return NULL; //Reads the receiver's public key for its file pubkey = retrieve_pubkey(pub_key_file); if(pubkey == NULL) return NULL; encrypted_key_len = EVP_PKEY_size(pubkey); total_output_size += encrypted_key_len; iv_len = EVP_CIPHER_iv_length(SYM_CIPHER); total_output_size += iv_len; //Allocation of encrypted symmetric key and initialization vector encrypted_key = malloc(encrypted_key_len); iv = malloc(iv_len); //Seeding the RNG RAND_seed(iv, 8); //Instantiate and initialize the context ctx = (EVP_CIPHER_CTX*)malloc(sizeof(EVP_CIPHER_CTX)); EVP_CIPHER_CTX_init(ctx); ret = EVP_SealInit(ctx, SYM_CIPHER, &encrypted_key, &encrypted_key_len, iv, &pubkey ,1); if(ret == 0){ fprintf(stderr, "Error in SealInit\n"); goto error; } //Encrypt the input buffer cipher_len = in_len + EVP_CIPHER_block_size(SYM_CIPHER); ciphertext = malloc(cipher_len); cipher_len = 0; ret = EVP_SealUpdate(ctx, ciphertext, &app, plaintext, in_len); cipher_len += app; if(ret == 0){ fprintf(stderr, "Error in SealUpdate\n"); goto error; } ret = EVP_SealFinal(ctx, ciphertext + app, &app); cipher_len += app; if(ret == 0){ fprintf(stderr, "Error in SealFinal\n"); goto error; } total_output_size += cipher_len; //Concatenates the envelop in the outbuffer with format: <IV><Dim_Key><Ecrypt_KEY><Ciphertext> total_output_size += sizeof(int); output = malloc(total_output_size); app = 0; //<IV> memcpy(output, iv, iv_len); app += iv_len; //<Dim_Key> memcpy(output + app, &encrypted_key_len, sizeof(int)); app += sizeof(int); //<Ecrypt_KEY> memcpy(output + app, encrypted_key, encrypted_key_len); app += encrypted_key_len; //<Ciphertext> memcpy(output + app, ciphertext, cipher_len); app += encrypted_key_len; *out_len = total_output_size; //Cleanup EVP_CIPHER_CTX_cleanup(ctx); free(ctx); free(ciphertext); free(pubkey); free(iv); return output; error: if(ctx != NULL){ EVP_CIPHER_CTX_cleanup(ctx); free(ctx); } if(encrypted_key != NULL) free(ciphertext); if(pubkey != NULL) free(pubkey); if(iv != NULL) free(iv); if(ciphertext != NULL) free(ciphertext); if(output != NULL) free(output); return NULL; }
/** Encrypt some data. * \param key_count Number of keys in the \a target array. * \param target Array of keys. Anyone who owns any of these keys will be * able to decrypt the data. These keys must include public key data. * \param data Group to encrypt. Will be replaced by an encrypted group. * \return Nonzero iff the operation succeeded. * \sa gale_crypto_target(), gale_crypto_open() */ int gale_crypto_seal( int key_count,const struct gale_group *target, struct gale_group *data) { struct gale_fragment frag; struct gale_data plain,cipher; EVP_CIPHER_CTX *context = EVP_CIPHER_CTX_new(); int i,*session_key_length; unsigned char **session_key,iv[EVP_MAX_IV_LENGTH]; struct gale_text *raw_name; EVP_PKEY **public_key; RSA *rsa; int good_count = 0,is_successful = 0; plain.p = gale_malloc(gale_group_size(*data) + gale_u32_size()); plain.l = 0; gale_pack_u32(&plain,0); /* version identifier? */ gale_pack_group(&plain,*data); *data = gale_group_empty(); gale_create_array(raw_name,key_count); gale_create_array(public_key,key_count); for (i = 0; i < key_count; ++i) public_key[i] = NULL; for (i = 0; i < key_count; ++i) { public_key[good_count] = EVP_PKEY_new(); EVP_PKEY_assign_RSA(public_key[good_count],RSA_new()); rsa = EVP_PKEY_get0_RSA(public_key[good_count]); raw_name[good_count] = key_i_swizzle(crypto_i_rsa( target[i],rsa)); if (0 != raw_name[good_count].l && crypto_i_public_valid(rsa)) ++good_count; else EVP_PKEY_free(public_key[good_count]); } gale_create_array(session_key_length,good_count); gale_create_array(session_key,good_count); for (i = 0; i < good_count; ++i) gale_create_array(session_key[i],EVP_PKEY_size(public_key[i])); crypto_i_seed(); if (!EVP_SealInit(context,EVP_des_ede3_cbc(), session_key,session_key_length,iv,public_key,good_count)) { crypto_i_error(); goto cleanup; } cipher.l = gale_copy_size(sizeof(magic2)) + gale_copy_size(EVP_CIPHER_CTX_iv_length(context)) + gale_u32_size() + plain.l + EVP_CIPHER_CTX_block_size(context) - 1; for (i = 0; i < good_count; ++i) cipher.l += gale_text_size(raw_name[i]) + gale_u32_size() + gale_copy_size(session_key_length[i]); cipher.p = gale_malloc(cipher.l); cipher.l = 0; assert(IV_LEN == EVP_CIPHER_CTX_iv_length(context)); gale_pack_copy(&cipher,magic2,sizeof(magic2)); gale_pack_copy(&cipher,iv,IV_LEN); gale_pack_u32(&cipher,good_count); for (i = 0; i < good_count; ++i) { gale_pack_text(&cipher,raw_name[i]); gale_pack_u32(&cipher,session_key_length[i]); gale_pack_copy(&cipher,session_key[i],session_key_length[i]); } EVP_SealUpdate(context,cipher.p + cipher.l,&i,plain.p,plain.l); cipher.l += i; EVP_SealFinal(context,cipher.p + cipher.l,&i); cipher.l += i; frag.type = frag_data; frag.name = G_("security/encryption"); frag.value.data = cipher; gale_group_add(data,frag); is_successful = 1; cleanup: for (i = 0; i < good_count; ++i) if (NULL != public_key[i]) EVP_PKEY_free(public_key[i]); return is_successful; }