/** * @brief Initialise a context for decrypting arbitrary data using the given key. * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If * *ctx is not NULL, *ctx must point at a previously created structure. * @param ctx The block context returned, see note. * @param blockSize The block size of the cipher. * @param iv Optional initialisation vector. If the buffer pointed to is NULL, * an IV will be created at random, in space allocated from the pool. * If the buffer is not NULL, the IV in the buffer will be used. * @param key The key structure. * @param p The pool to use. * @return Returns APR_ENOIV if an initialisation vector is required but not specified. * Returns APR_EINIT if the backend failed to initialise the context. Returns * APR_ENOTIMPL if not implemented. */ static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx, apr_size_t *blockSize, const unsigned char *iv, const apr_crypto_key_t *key, apr_pool_t *p) { apr_crypto_config_t *config = key->f->config; apr_crypto_block_t *block = *ctx; if (!block) { *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t)); } if (!block) { return APR_ENOMEM; } block->f = key->f; block->pool = p; block->provider = key->provider; apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper, apr_pool_cleanup_null); /* create a new context for encryption */ if (!block->initialised) { block->cipherCtx = EVP_CIPHER_CTX_new(); block->initialised = 1; } /* generate an IV, if necessary */ if (key->ivSize) { if (iv == NULL) { return APR_ENOIV; } } /* set up our encryption context */ #if CRYPTO_OPENSSL_CONST_BUFFERS if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, key->key, iv)) { #else if (!EVP_DecryptInit_ex(block->cipherCtx, key->cipher, config->engine, (unsigned char *) key->key, (unsigned char *) iv)) { #endif return APR_EINIT; } /* Clear up any read padding */ if (!EVP_CIPHER_CTX_set_padding(block->cipherCtx, key->doPad)) { return APR_EPADDING; } if (blockSize) { *blockSize = EVP_CIPHER_block_size(key->cipher); } return APR_SUCCESS; } /** * @brief Decrypt data provided by in, write it to out. * @note The number of bytes written will be written to outlen. If * out is NULL, outlen will contain the maximum size of the * buffer needed to hold the data, including any data * generated by apr_crypto_block_decrypt_finish below. If *out points * to NULL, a buffer sufficiently large will be created from * the pool provided. If *out points to a not-NULL value, this * value will be used as a buffer instead. * @param out Address of a buffer to which data will be written, * see note. * @param outlen Length of the output will be written here. * @param in Address of the buffer to read. * @param inlen Length of the buffer to read. * @param ctx The block context to use. * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if * not implemented. */ static apr_status_t crypto_block_decrypt(unsigned char **out, apr_size_t *outlen, const unsigned char *in, apr_size_t inlen, apr_crypto_block_t *ctx) { int outl = *outlen; unsigned char *buffer; /* are we after the maximum size of the out buffer? */ if (!out) { *outlen = inlen + EVP_MAX_BLOCK_LENGTH; return APR_SUCCESS; } /* must we allocate the output buffer from a pool? */ if (!(*out)) { buffer = apr_palloc(ctx->pool, inlen + EVP_MAX_BLOCK_LENGTH); if (!buffer) { return APR_ENOMEM; } apr_crypto_clear(ctx->pool, buffer, inlen + EVP_MAX_BLOCK_LENGTH); *out = buffer; } #if CRYPT_OPENSSL_CONST_BUFFERS if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, in, inlen)) { #else if (!EVP_DecryptUpdate(ctx->cipherCtx, *out, &outl, (unsigned char *) in, inlen)) { #endif #if APR_USE_OPENSSL_PRE_1_1_API EVP_CIPHER_CTX_cleanup(ctx->cipherCtx); #else EVP_CIPHER_CTX_reset(ctx->cipherCtx); #endif return APR_ECRYPT; } *outlen = outl; return APR_SUCCESS; } /** * @brief Decrypt final data block, write it to out. * @note If necessary the final block will be written out after being * padded. Typically the final block will be written to the * same buffer used by apr_crypto_block_decrypt, offset by the * number of bytes returned as actually written by the * apr_crypto_block_decrypt() call. After this call, the context * is cleaned and can be reused by apr_crypto_block_decrypt_init(). * @param out Address of a buffer to which data will be written. This * buffer must already exist, and is usually the same * buffer used by apr_evp_crypt(). See note. * @param outlen Length of the output will be written here. * @param ctx The block context to use. * @return APR_ECRYPT if an error occurred. * @return APR_EPADDING if padding was enabled and the block was incorrectly * formatted. * @return APR_ENOTIMPL if not implemented. */ static apr_status_t crypto_block_decrypt_finish(unsigned char *out, apr_size_t *outlen, apr_crypto_block_t *ctx) { apr_status_t rc = APR_SUCCESS; int len = *outlen; if (EVP_DecryptFinal_ex(ctx->cipherCtx, out, &len) == 0) { rc = APR_EPADDING; } else { *outlen = len; } #if APR_USE_OPENSSL_PRE_1_1_API EVP_CIPHER_CTX_cleanup(ctx->cipherCtx); #else EVP_CIPHER_CTX_reset(ctx->cipherCtx); #endif return rc; }
int seafile_decrypt (char **data_out, int *out_len, const char *data_in, const int in_len, SeafileCrypt *crypt) { *data_out = NULL; *out_len = -1; /* Check validation. Because padding is always used, in_len must * be a multiple of BLK_SIZE */ if ( data_in == NULL || in_len <= 0 || in_len % BLK_SIZE != 0 || crypt == NULL) { g_warning ("Invalid param(s).\n"); return -1; } EVP_CIPHER_CTX ctx; int ret; /* Prepare CTX for decryption. */ EVP_CIPHER_CTX_init (&ctx); if (crypt->version >= 1) ret = EVP_DecryptInit_ex (&ctx, EVP_aes_128_cbc(), /* cipher mode */ NULL, /* engine, NULL for default */ crypt->key, /* derived key */ crypt->iv); /* initial vector */ else ret = EVP_DecryptInit_ex (&ctx, EVP_aes_128_ecb(), /* cipher mode */ NULL, /* engine, NULL for default */ crypt->key, /* derived key */ crypt->iv); /* initial vector */ if (ret == DEC_FAILURE) return -1; /* Allocating output buffer. */ *data_out = (char *)g_malloc (in_len); if (*data_out == NULL) { g_warning ("failed to allocate the output buffer.\n"); goto dec_error; } int update_len, final_len; /* Do the decryption. */ ret = EVP_DecryptUpdate (&ctx, (unsigned char*)*data_out, &update_len, (unsigned char*)data_in, in_len); if (ret == DEC_FAILURE) goto dec_error; /* Finish the possible partial block. */ ret = EVP_DecryptFinal_ex (&ctx, (unsigned char*)*data_out + update_len, &final_len); *out_len = update_len + final_len; /* out_len should be smaller than in_len. */ if (ret == DEC_FAILURE || *out_len > in_len) goto dec_error; EVP_CIPHER_CTX_cleanup (&ctx); return 0; dec_error: EVP_CIPHER_CTX_cleanup (&ctx); *out_len = -1; if (*data_out != NULL) g_free (*data_out); *data_out = NULL; return -1; }
Item *aes_gcm_decrypt(EncItem *ct, SymKey *key) { EVP_CIPHER_CTX *ctx; int aad_len = sizeof(gcm_aad); int len; int rc; if(key == NULL || ct == NULL) { printf("%s :: Invalid input\n", __func__); return NULL; } Item *pt = new Item(CRYPT_ITEM_MAX_LEN); if(pt == NULL) { printf("%s :: no Memory\n", __func__); return NULL; } /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } EVP_CIPHER_CTX_set_padding(ctx, 0); /* Initialise the decryption operation. */ if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Initialise key and IV */ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key->getData(), gcm_iv)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, ct->auth_tag)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Provide any AAD data. This can be called zero or more times as * required */ if(!EVP_DecryptUpdate(ctx, NULL, &len, gcm_aad, aad_len)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if(!EVP_DecryptUpdate(ctx, pt->getData(), &len, ct->getData(), ct->len)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } pt->len = len; /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, ct->auth_tag)) { printf("error %s:%d\n", __func__, __LINE__); goto err_out; } /* Finalise the decryption. A positive return value indicates success, * anything else is a failure - the plaintext is not trustworthy. */ rc = EVP_DecryptFinal_ex(ctx, pt->getData() + len, &len); /* Clean up */ EVP_CIPHER_CTX_free(ctx); if(rc > 0) { /* Success */ pt->len += len; return pt; } else /* Verify failed */ printf("error %s:%d GCM verify failed\n", __func__, __LINE__); err_out: delete pt; return NULL; }
BOOL CHTTPCrypt::decrypt(CString &csInput, CString &csOutput) { EVP_CIPHER_CTX oEncCtx; const EVP_CIPHER *oChiper = NULL; int nSep; UINT uLength; LPBYTE pOutBuffer = NULL, pOutPaddingBuffer = NULL, pInitVector = NULL, pInBuffer = NULL; int nOutBufferLength, nOutPaddingLength; CString csBuffer; // Set aes key switch (m_csKey.GetLength()) { case 16: oChiper = EVP_aes_128_cbc(); break; case 32: oChiper = EVP_aes_256_cbc(); break; default: // Wrong key size return FALSE; } csOutput.Empty(); // Get initialization vector from input string and base64 decode it if ((nSep = csInput.Find( OCS_HTTP_SEPARATOR_VALUE)) <= 0) return FALSE; csBuffer = csInput.Left( nSep); if ((pInitVector = base64_decode( csBuffer, &uLength)) == NULL) return FALSE; // Create decryption context using initialization vector EVP_CIPHER_CTX_init( &oEncCtx); EVP_DecryptInit_ex( &oEncCtx, oChiper, 0, (LPBYTE) LPCSTR( m_csKey), pInitVector); free( pInitVector); // Get real encrypted data from input string csBuffer = csInput.Mid( nSep+_tcslen( OCS_HTTP_SEPARATOR_VALUE), csInput.GetLength()-nSep-_tcslen( OCS_HTTP_SEPARATOR_VALUE)); if ((pInBuffer = base64_decode( csBuffer, &uLength)) == NULL) { return FALSE; } // Decrypt most of the data nOutBufferLength = uLength; if ((pOutBuffer = (LPBYTE) malloc( nOutBufferLength)) == NULL) { free( pInBuffer); return FALSE; } memset( pOutBuffer, 0, nOutBufferLength); if (EVP_DecryptUpdate( &oEncCtx, pOutBuffer, &nOutBufferLength, pInBuffer, nOutBufferLength) < 0) { // Decryption fail free( pInBuffer); free( pOutBuffer); return FALSE; } // Decrypt last block+padding: pOutPaddingBuffer = pOutBuffer + nOutBufferLength; nOutPaddingLength = nOutBufferLength; if (EVP_DecryptFinal_ex( &oEncCtx, pOutPaddingBuffer, &nOutPaddingLength) < 0) { // Decryption fail free( pInBuffer); free( pOutBuffer); return FALSE; } // Copy decrypted data to output for (nSep = 0; (nSep<nOutBufferLength+nOutPaddingLength) && (pOutBuffer[nSep]!=0); nSep++) csOutput.AppendFormat( _T( "%c"), pOutBuffer[nSep]); free( pInBuffer); free( pOutBuffer); EVP_CIPHER_CTX_cleanup(&oEncCtx); return TRUE; }
/* DES3-EDE unwrap operation loosely based on to RFC 2630, section 12.6 * wrapped_key has to be 40 bytes in length. */ int apple_des3_ede_unwrap_key(uint8_t *wrapped_key, int wrapped_key_len, uint8_t *decryptKey, uint8_t *unwrapped_key) { EVP_CIPHER_CTX ctx; uint8_t *TEMP1, *TEMP2, *CEKICV; uint8_t IV[8] = { 0x4a, 0xdd, 0xa2, 0x2c, 0x79, 0xe8, 0x21, 0x05 }; int outlen, tmplen, i; EVP_CIPHER_CTX_init(&ctx); /* result of the decryption operation shouldn't be bigger than ciphertext */ TEMP1 = malloc(wrapped_key_len); TEMP2 = malloc(wrapped_key_len); CEKICV = malloc(wrapped_key_len); /* uses PKCS#7 padding for symmetric key operations by default */ EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, decryptKey, IV); if(!EVP_DecryptUpdate(&ctx, TEMP1, &outlen, wrapped_key, wrapped_key_len)) { fprintf(stderr, "internal error (1) during key unwrap operation!\n"); return(-1); } if(!EVP_DecryptFinal_ex(&ctx, TEMP1 + outlen, &tmplen)) { fprintf(stderr, "internal error (2) during key unwrap operation!\n"); return(-1); } outlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); /* reverse order of TEMP3 */ for(i = 0; i < outlen; i++) { TEMP2[i] = TEMP1[outlen - i - 1]; } EVP_CIPHER_CTX_init(&ctx); /* uses PKCS#7 padding for symmetric key operations by default */ EVP_DecryptInit_ex(&ctx, EVP_des_ede3_cbc(), NULL, decryptKey, TEMP2); if(!EVP_DecryptUpdate(&ctx, CEKICV, &outlen, TEMP2+8, outlen-8)) { fprintf(stderr, "internal error (3) during key unwrap operation!\n"); return(-1); } if(!EVP_DecryptFinal_ex(&ctx, CEKICV + outlen, &tmplen)) { fprintf(stderr, "internal error (4) during key unwrap operation!\n"); return(-1); } outlen += tmplen; EVP_CIPHER_CTX_cleanup(&ctx); /* * from libsecurity_apple_csp-12/lib/wrapKeyCms.cpp: * * XXX ;) --- we assume the length of the descriptive data to be zero * * 1. PRIVATE_KEY_BYTES is the private data to be wrapped. It consists of the * following concatenation: * * 4-byte length of Descriptive Data, big-endian | * Descriptive Data | * rawBlob.Data bytes */ memcpy(unwrapped_key, CEKICV+4, outlen-4); free(TEMP1); free(TEMP2); free(CEKICV); return(0); }
//TODO (ANY#8#): Simplify Encryption functions by using EVP_CipherInit_ex instead of Decrypt and Encrypt variants. int cmeCipherInit (EVP_CIPHER_CTX **ctx, ENGINE *engine, const EVP_CIPHER *cipher, unsigned char *key, unsigned char* iv, char mode) { int result; *ctx=(EVP_CIPHER_CTX *)malloc(sizeof(EVP_CIPHER_CTX)); if ((mode!='d')&&(mode!='e')) { #ifdef ERROR_LOG fprintf(stderr,"CaumeDSE Error: evpCipherInit(), unknown cipher mode '%c'!\n",mode); #endif return (1); } else { #ifdef DEBUG fprintf(stdout,"CaumeDSE Debug: evpCipherInit(), cipher mode '%c' selected.\n",mode); #endif EVP_CIPHER_CTX_init(*ctx); //Initialize Cipher context if (mode=='e') //Encrypt { result= EVP_EncryptInit_ex(*ctx,cipher,engine,key,iv); if (result==0) //1= success, 0=failure { #ifdef ERROR_LOG fprintf(stderr,"CaumeDSE Error: evpCipherInit(), EVP_EncryptInit_ex() failure!\n"); #endif return (2); } else { #ifdef DEBUG fprintf(stdout,"CaumeDSE Debug: evpCipherInit(), EVP_EncryptInit_ex() success.\n"); #endif } } else //Decrypt { result= EVP_DecryptInit_ex(*ctx,cipher,engine,key,iv); if (result==0) //1= success, 0=failure { #ifdef ERROR_LOG fprintf(stderr,"CaumeDSE Error: evpCipherInit(), EVP_DecryptInit_ex() failure!\n"); #endif return (2); } else { #ifdef DEBUG fprintf(stdout,"CaumeDSE Debug: evpCipherInit(), EVP_DecryptInit_ex() success.\n"); #endif } } } return (0); }
static EVP_PKEY * do_PVK_body(const unsigned char **in, unsigned int saltlen, unsigned int keylen, pem_password_cb *cb, void *u) { EVP_PKEY *ret = NULL; const unsigned char *p = *in; unsigned int magic; unsigned char *enctmp = NULL, *q; EVP_CIPHER_CTX cctx; EVP_CIPHER_CTX_init(&cctx); if (saltlen) { char psbuf[PEM_BUFSIZE]; unsigned char keybuf[20]; int enctmplen, inlen; if (cb) inlen = cb(psbuf, PEM_BUFSIZE, 0, u); else inlen = PEM_def_callback(psbuf, PEM_BUFSIZE, 0, u); if (inlen <= 0) { PEMerror(PEM_R_BAD_PASSWORD_READ); goto err; } enctmp = malloc(keylen + 8); if (!enctmp) { PEMerror(ERR_R_MALLOC_FAILURE); goto err; } if (!derive_pvk_key(keybuf, p, saltlen, (unsigned char *)psbuf, inlen)) { goto err; } p += saltlen; /* Copy BLOBHEADER across, decrypt rest */ memcpy(enctmp, p, 8); p += 8; if (keylen < 8) { PEMerror(PEM_R_PVK_TOO_SHORT); goto err; } inlen = keylen - 8; q = enctmp + 8; if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) goto err; if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) goto err; if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) goto err; magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { q = enctmp + 8; memset(keybuf + 5, 0, 11); if (!EVP_DecryptInit_ex(&cctx, EVP_rc4(), NULL, keybuf, NULL)) goto err; explicit_bzero(keybuf, 20); if (!EVP_DecryptUpdate(&cctx, q, &enctmplen, p, inlen)) goto err; if (!EVP_DecryptFinal_ex(&cctx, q + enctmplen, &enctmplen)) goto err; magic = read_ledword((const unsigned char **)&q); if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) { PEMerror(PEM_R_BAD_DECRYPT); goto err; } } else explicit_bzero(keybuf, 20); p = enctmp; } ret = b2i_PrivateKey(&p, keylen); err: EVP_CIPHER_CTX_cleanup(&cctx); if (enctmp && saltlen) free(enctmp); return ret; }
int eap_fast_decrypt(uint8_t const *ciphertext, size_t ciphertext_len, uint8_t const *aad, size_t aad_len, uint8_t const *tag, uint8_t const *key, uint8_t const *iv, uint8_t *plaintext) { EVP_CIPHER_CTX *ctx; int len; int plaintext_len; int ret; /* Create and initialise the context */ if (!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the decryption operation. */ if (!EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL)) handleErrors(); /* Set IV length. Not necessary if this is 12 bytes (96 bits) */ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, 16, NULL)) handleErrors(); /* Initialise key and IV */ if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ if (!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); /* Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if (!EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len)) handleErrors(); plaintext_len = len; { unsigned char *tmp; memcpy(&tmp, &tag, sizeof(tmp)); /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tmp)) handleErrors(); } /* Finalise the decryption. A positive return value indicates success, * anything else is a failure - the plaintext is not trustworthy. */ ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); /* Clean up */ EVP_CIPHER_CTX_free(ctx); if (ret > 0) { /* Success */ plaintext_len += len; return plaintext_len; } else { /* Verify failed */ return -1; } }
PPH_ERROR pph_check_login(pph_context *ctx, const char *username, unsigned int username_length, uint8 *password, unsigned int password_length){ // this will be used to iterate all the users pph_account_node *search; pph_account_node *target = NULL; // we will store the current share in this buffer for xor'ing uint8 share_data[SHARE_LENGTH]; // we will calculate a "proposed hash" in this buffer uint8 resulting_hash[DIGEST_LENGTH]; uint8 salted_password[MAX_SALT_LENGTH+MAX_PASSWORD_LENGTH]; uint8 xored_hash[SHARE_LENGTH]; // these are value holders to improve readability uint8 sharenumber; pph_entry *current_entry; unsigned int i; // this will hold an offset value for partial verification. unsigned int partial_bytes_offset; // openSSL managers. EVP_CIPHER_CTX de_ctx; int p_len,f_len; // 1) Sanitize data and return errors. // check for any improper pointers if(ctx == NULL || username == NULL || password == NULL){ return PPH_BAD_PTR; } // if the length is too long for either field, return proper error. if(username_length > MAX_USERNAME_LENGTH){ return PPH_USERNAME_IS_TOO_LONG; } // do the same for the password if(password_length > MAX_PASSWORD_LENGTH){ return PPH_PASSWORD_IS_TOO_LONG; } // check if the context is locked and we lack partial bytes to check. If we // do not have enough partial bytes (at least one), we cannot do partial // verification if(ctx->is_unlocked != true && ctx->partial_bytes == 0){ return PPH_CONTEXT_IS_LOCKED; } // check we have a thresholdless key if(ctx->AES_key == NULL && ctx->partial_bytes == 0){ return PPH_CONTEXT_IS_LOCKED; } // 2) Try to find the user in our context. // search for our user, we search the entries with the same username length // first, and then we check if the contents are the same. search = ctx->account_data; while(search!=NULL){ // we check lengths first and then compare what's in it. if(username_length == search->account.username_length && !memcmp(search->account.username,username,username_length)){ target = search; } search=search->next; } //i.e. we found no one if(target == NULL){ return PPH_ACCOUNT_IS_INVALID; } // if we reach here, we should have enough resources to provide a login // functionality to the user. // 3) Try to verify the proper password for him. // first, check what type of account is this // this probably happens if data is inconsistent, but let's avoid // segmentation faults. if(target->account.entries == NULL){ return PPH_ERROR_UNKNOWN; } // we get the first entry to check if this is a valid login, we could be // thorough and check for each, but it looks like an overkill current_entry = target->account.entries; sharenumber = current_entry->share_number; partial_bytes_offset = DIGEST_LENGTH - ctx->partial_bytes; // if the context is not unlocked, we can only provide partial verification if(ctx->is_unlocked != true){ // partial bytes check // calculate the proposed digest, this means, calculate the hash with // the information just provided about the user. memcpy(salted_password,current_entry->salt,current_entry->salt_length); memcpy(salted_password+current_entry->salt_length, password, current_entry->password_length); _calculate_digest(resulting_hash, salted_password, current_entry->salt_length + password_length); // only compare the bytes that are not obscured by either AES or the // share, we start from share_length-partial_bytes to share_length. if(memcmp(resulting_hash+partial_bytes_offset, target->account.entries->polyhashed_value+partial_bytes_offset, ctx->partial_bytes)){ return PPH_ACCOUNT_IS_INVALID; } return PPH_ERROR_OK; } // we are unlocked and hence we can provide full verification. else{ // first, check if the account is a threshold or thresholdless account. if(sharenumber == 0){ // if the sharenumber is 0 then we have a thresholdless account // now we should calculate the expected hash by deciphering the // information inside the context. EVP_CIPHER_CTX_init(&de_ctx); EVP_DecryptInit_ex(&de_ctx, EVP_aes_256_ctr(), NULL, ctx->AES_key, NULL); EVP_DecryptUpdate(&de_ctx, xored_hash, &p_len, current_entry->polyhashed_value, partial_bytes_offset); EVP_DecryptFinal_ex(&de_ctx, xored_hash+p_len, &f_len); EVP_CIPHER_CTX_cleanup(&de_ctx); // append the unencrypted bytes if we have partial bytes. for(i=p_len+f_len;i<DIGEST_LENGTH;i++){ xored_hash[i] = current_entry->polyhashed_value[i]; } // calculate the proposed digest with the parameters provided in // this function. memcpy(salted_password,current_entry->salt, current_entry->salt_length); memcpy(salted_password+current_entry->salt_length, password, password_length); _calculate_digest(resulting_hash, salted_password, current_entry->salt_length + password_length); // 3) compare both, and they should match. if(memcmp(resulting_hash, xored_hash, DIGEST_LENGTH)){ return PPH_ACCOUNT_IS_INVALID; } return PPH_ERROR_OK; }else{ // we have a non thresholdless account instead, since the sharenumber is // not 0 gfshare_ctx_enc_getshare(ctx->share_context, sharenumber, share_data); // calculate the proposed digest with the salt from the account and // the password in the argument. memcpy(salted_password,current_entry->salt, current_entry->salt_length); memcpy(salted_password+current_entry->salt_length, password, password_length); _calculate_digest(resulting_hash, salted_password, current_entry->salt_length + password_length); // xor the thing back to normal _xor_share_with_digest(xored_hash,current_entry->polyhashed_value, share_data, partial_bytes_offset); // add the partial bytes to the end of the digest. for(i=DIGEST_LENGTH-ctx->partial_bytes;i<DIGEST_LENGTH;i++){ xored_hash[i] = target->account.entries->polyhashed_value[i]; } // compare both. if(memcmp(resulting_hash, xored_hash, DIGEST_LENGTH)){ return PPH_ACCOUNT_IS_INVALID; } return PPH_ERROR_OK; // this means, the login does match } } // if we get to reach here, we where diverged from usual flow. return PPH_ERROR_UNKNOWN; }
static void test1(const EVP_CIPHER *c, const unsigned char *key, int kn, const unsigned char *iv, int in, const unsigned char *plaintext, int pn, const unsigned char *ciphertext, int cn, const unsigned char *aad, int an, const unsigned char *tag, int tn, int encdec) { EVP_CIPHER_CTX ctx; unsigned char out[4096]; int outl, outl2, mode; printf("Testing cipher %s%s\n", EVP_CIPHER_name(c), (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)"))); hexdump(stdout, "Key", key, kn); if (in) hexdump(stdout, "IV", iv, in); hexdump(stdout, "Plaintext", plaintext, pn); hexdump(stdout, "Ciphertext", ciphertext, cn); if (an) hexdump(stdout, "AAD", aad, an); if (tn) hexdump(stdout, "Tag", tag, tn); mode = EVP_CIPHER_mode(c); if (kn != EVP_CIPHER_key_length(c)) { fprintf(stderr, "Key length doesn't match, got %d expected %lu\n", kn, (unsigned long)EVP_CIPHER_key_length(c)); test1_exit(5); } EVP_CIPHER_CTX_init(&ctx); EVP_CIPHER_CTX_set_flags(&ctx, EVP_CIPHER_CTX_FLAG_WRAP_ALLOW); if (encdec != 0) { if (mode == EVP_CIPH_GCM_MODE) { if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) { fprintf(stderr, "IV length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) { fprintf(stderr, "Key/IV set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) { fprintf(stderr, "AAD set failed\n"); ERR_print_errors_fp(stderr); test1_exit(13); } } else if (mode == EVP_CIPH_CCM_MODE) { if (!EVP_EncryptInit_ex(&ctx, c, NULL, NULL, NULL)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) { fprintf(stderr, "IV length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, tn, NULL)) { fprintf(stderr, "Tag length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_EncryptInit_ex(&ctx, NULL, NULL, key, iv)) { fprintf(stderr, "Key/IV set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (!EVP_EncryptUpdate(&ctx, NULL, &outl, NULL, pn)) { fprintf(stderr, "Plaintext length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) { fprintf(stderr, "AAD set failed\n"); ERR_print_errors_fp(stderr); test1_exit(13); } } else if (mode == EVP_CIPH_WRAP_MODE) { if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } } else if (!EVP_EncryptInit_ex(&ctx, c, NULL, key, iv)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } EVP_CIPHER_CTX_set_padding(&ctx, 0); if (!EVP_EncryptUpdate(&ctx, out, &outl, plaintext, pn)) { fprintf(stderr, "Encrypt failed\n"); ERR_print_errors_fp(stderr); test1_exit(6); } if (!EVP_EncryptFinal_ex(&ctx, out + outl, &outl2)) { fprintf(stderr, "EncryptFinal failed\n"); ERR_print_errors_fp(stderr); test1_exit(7); } if (outl + outl2 != cn) { fprintf(stderr, "Ciphertext length mismatch got %d expected %d\n", outl + outl2, cn); test1_exit(8); } if (memcmp(out, ciphertext, cn)) { fprintf(stderr, "Ciphertext mismatch\n"); hexdump(stderr, "Got", out, cn); hexdump(stderr, "Expected", ciphertext, cn); test1_exit(9); } if (mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_CCM_MODE) { unsigned char rtag[16]; /* * Note: EVP_CTRL_CCM_GET_TAG has same value as * EVP_CTRL_GCM_GET_TAG */ if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_GET_TAG, tn, rtag)) { fprintf(stderr, "Get tag failed\n"); ERR_print_errors_fp(stderr); test1_exit(14); } if (memcmp(rtag, tag, tn)) { fprintf(stderr, "Tag mismatch\n"); hexdump(stderr, "Got", rtag, tn); hexdump(stderr, "Expected", tag, tn); test1_exit(9); } } } if (encdec <= 0) { if (mode == EVP_CIPH_GCM_MODE) { if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_IVLEN, in, NULL)) { fprintf(stderr, "IV length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) { fprintf(stderr, "Key/IV set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (!EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_GCM_SET_TAG, tn, (void *)tag)) { fprintf(stderr, "Set tag failed\n"); ERR_print_errors_fp(stderr); test1_exit(14); } if (an && !EVP_DecryptUpdate(&ctx, NULL, &outl, aad, an)) { fprintf(stderr, "AAD set failed\n"); ERR_print_errors_fp(stderr); test1_exit(13); } } else if (mode == EVP_CIPH_CCM_MODE) { if (!EVP_DecryptInit_ex(&ctx, c, NULL, NULL, NULL)) { fprintf(stderr, "DecryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } if (!EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_IVLEN, in, NULL)) { fprintf(stderr, "IV length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_CIPHER_CTX_ctrl (&ctx, EVP_CTRL_CCM_SET_TAG, tn, (void *)tag)) { fprintf(stderr, "Tag length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } if (!EVP_DecryptInit_ex(&ctx, NULL, NULL, key, iv)) { fprintf(stderr, "Key/Nonce set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (!EVP_DecryptUpdate(&ctx, NULL, &outl, NULL, pn)) { fprintf(stderr, "Plaintext length set failed\n"); ERR_print_errors_fp(stderr); test1_exit(12); } if (an && !EVP_EncryptUpdate(&ctx, NULL, &outl, aad, an)) { fprintf(stderr, "AAD set failed\n"); ERR_print_errors_fp(stderr); test1_exit(13); } } else if (mode == EVP_CIPH_WRAP_MODE) { if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, in ? iv : NULL)) { fprintf(stderr, "EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } } else if (!EVP_DecryptInit_ex(&ctx, c, NULL, key, iv)) { fprintf(stderr, "DecryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } EVP_CIPHER_CTX_set_padding(&ctx, 0); if (!EVP_DecryptUpdate(&ctx, out, &outl, ciphertext, cn)) { fprintf(stderr, "Decrypt failed\n"); ERR_print_errors_fp(stderr); test1_exit(6); } if (mode != EVP_CIPH_CCM_MODE && !EVP_DecryptFinal_ex(&ctx, out + outl, &outl2)) { fprintf(stderr, "DecryptFinal failed\n"); ERR_print_errors_fp(stderr); test1_exit(7); } if (outl + outl2 != pn) { fprintf(stderr, "Plaintext length mismatch got %d expected %d\n", outl + outl2, pn); test1_exit(8); } if (memcmp(out, plaintext, pn)) { fprintf(stderr, "Plaintext mismatch\n"); hexdump(stderr, "Got", out, pn); hexdump(stderr, "Expected", plaintext, pn); test1_exit(9); } } EVP_CIPHER_CTX_cleanup(&ctx); printf("\n"); }
int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size, AgentConnection *conn) { int dd, blocksize = 2048, n_read = 0, towrite, plainlen, more = true, finlen, cnt = 0; int tosend, cipherlen = 0; char *buf, in[CF_BUFSIZE], out[CF_BUFSIZE], workbuf[CF_BUFSIZE], cfchangedstr[265]; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; long n_read_total = 0; EVP_CIPHER_CTX crypto_ctx; snprintf(cfchangedstr, 255, "%s%s", CF_CHANGEDSTR1, CF_CHANGEDSTR2); if ((strlen(dest) > CF_BUFSIZE - 20)) { Log(LOG_LEVEL_ERR, "Filename too long"); return false; } unlink(dest); /* To avoid link attacks */ if ((dd = safe_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600)) == -1) { Log(LOG_LEVEL_ERR, "Copy from server '%s' to destination '%s' failed (open: %s)", conn->this_server, dest, GetErrorStr()); unlink(dest); return false; } if (size == 0) { // No sense in copying an empty file close(dd); return true; } workbuf[0] = '\0'; EVP_CIPHER_CTX_init(&crypto_ctx); snprintf(in, CF_BUFSIZE - CF_PROTO_OFFSET, "GET dummykey %s", source); cipherlen = EncryptString(conn->encryption_type, in, out, conn->session_key, strlen(in) + 1); snprintf(workbuf, CF_BUFSIZE, "SGET %4d %4d", cipherlen, blocksize); memcpy(workbuf + CF_PROTO_OFFSET, out, cipherlen); tosend = cipherlen + CF_PROTO_OFFSET; /* Send proposition C0 - query */ if (SendTransaction(conn->conn_info, workbuf, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Couldn't send data. (SendTransaction: %s)", GetErrorStr()); close(dd); return false; } buf = xmalloc(CF_BUFSIZE + sizeof(int)); n_read_total = 0; while (more) { if ((cipherlen = ReceiveTransaction(conn->conn_info, buf, &more)) == -1) { free(buf); return false; } cnt++; /* If the first thing we get is an error message, break. */ if ((n_read_total == 0) && (strncmp(buf + CF_INBAND_OFFSET, CF_FAILEDSTR, strlen(CF_FAILEDSTR)) == 0)) { Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, source); close(dd); free(buf); return false; } if (strncmp(buf + CF_INBAND_OFFSET, cfchangedstr, strlen(cfchangedstr)) == 0) { Log(LOG_LEVEL_INFO, "Source '%s:%s' changed while copying", conn->this_server, source); close(dd); free(buf); return false; } EVP_DecryptInit_ex(&crypto_ctx, CfengineCipher(CfEnterpriseOptions()), NULL, conn->session_key, iv); if (!EVP_DecryptUpdate(&crypto_ctx, workbuf, &plainlen, buf, cipherlen)) { close(dd); free(buf); return false; } if (!EVP_DecryptFinal_ex(&crypto_ctx, workbuf + plainlen, &finlen)) { close(dd); free(buf); return false; } towrite = n_read = plainlen + finlen; n_read_total += n_read; if (!FSWrite(dest, dd, workbuf, towrite)) { Log(LOG_LEVEL_ERR, "Local disk write failed copying '%s:%s' to '%s:%s'", conn->this_server, source, dest, GetErrorStr()); if (conn) { conn->error = true; } free(buf); unlink(dest); close(dd); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } } /* If the file ends with a `hole', something needs to be written at the end. Otherwise the kernel would truncate the file at the end of the last write operation. Write a null character and truncate it again. */ if (ftruncate(dd, n_read_total) < 0) { Log(LOG_LEVEL_ERR, "Copy failed (no space?) while copying '%s' from network '%s'", dest, GetErrorStr()); free(buf); unlink(dest); close(dd); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } close(dd); free(buf); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return true; }
int AesWrappers::Decrypt(const unsigned char* const key, const unsigned char* const iv, const unsigned char* const msg, const unsigned int& msg_len, unsigned char*& result, unsigned int* result_len) { FUNCTION_START; #ifdef EVALUATE clock_t start = clock(); #endif EVP_CIPHER_CTX ctx; unsigned int res_len = 0; unsigned int length = 0; int temp_len = 0; const EVP_CIPHER* cipher = EVP_aes_256_cbc(); if (key == nullptr || iv == nullptr || msg == nullptr) { RETURN_STATUS(NULL_ARG); } if (result_len != nullptr) { *result_len = 0; } // allocate space for result res_len = msg_len + EVP_CIPHER_block_size(cipher); result = (unsigned char*)malloc(res_len); if (result == nullptr) { RETURN_STATUS(MALLOC_FAILURE); } // Init cipher and encrption EVP_CIPHER_CTX_init(&ctx); returned_value = EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv); if (returned_value != 1) { RETURN_STATUS(OPENSSL_ERROR); } returned_value = EVP_DecryptUpdate(&ctx, result, &temp_len, msg, msg_len); if (returned_value != 1) { RETURN_STATUS(OPENSSL_ERROR); } length += temp_len; returned_value = EVP_DecryptFinal_ex(&ctx, result + length, &temp_len); if (returned_value != 1) { RETURN_STATUS(OPENSSL_ERROR); } length += temp_len; if (result_len != nullptr) { *result_len = length; } exit: #ifdef EVALUATE if (status == SUCCESS) { clock_t end = clock(); TIME_AES_DECRYPTS += ((double) end - start) / CLOCKS_PER_SEC; ++NUM_AES_DECRYPTS; } #endif EVP_CIPHER_CTX_cleanup(&ctx); if (status != SUCCESS) { free(result); } FUNCTION_END; }
static void receive_udppacket(node_t *n, vpn_packet_t *inpkt) { vpn_packet_t pkt1, pkt2; vpn_packet_t *pkt[] = { &pkt1, &pkt2, &pkt1, &pkt2 }; int nextpkt = 0; vpn_packet_t *outpkt = pkt[0]; int outlen, outpad; unsigned char hmac[EVP_MAX_MD_SIZE]; int i; if(!n->inkey) { ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got packet from %s (%s) but he hasn't got our key yet", n->name, n->hostname); return; } /* Check packet length */ if(inpkt->len < sizeof(inpkt->seqno) + n->inmaclength) { ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got too short packet from %s (%s)", n->name, n->hostname); return; } /* Check the message authentication code */ if(n->indigest && n->inmaclength) { inpkt->len -= n->inmaclength; HMAC(n->indigest, n->inkey, n->inkeylength, (unsigned char *) &inpkt->seqno, inpkt->len, (unsigned char *)hmac, NULL); if(memcmp_constant_time(hmac, (char *) &inpkt->seqno + inpkt->len, n->inmaclength)) { ifdebug(TRAFFIC) logger(LOG_DEBUG, "Got unauthenticated packet from %s (%s)", n->name, n->hostname); return; } } /* Decrypt the packet */ if(n->incipher) { outpkt = pkt[nextpkt++]; if(!EVP_DecryptInit_ex(&n->inctx, NULL, NULL, NULL, NULL) || !EVP_DecryptUpdate(&n->inctx, (unsigned char *) &outpkt->seqno, &outlen, (unsigned char *) &inpkt->seqno, inpkt->len) || !EVP_DecryptFinal_ex(&n->inctx, (unsigned char *) &outpkt->seqno + outlen, &outpad)) { ifdebug(TRAFFIC) logger(LOG_DEBUG, "Error decrypting packet from %s (%s): %s", n->name, n->hostname, ERR_error_string(ERR_get_error(), NULL)); return; } outpkt->len = outlen + outpad; inpkt = outpkt; } /* Check the sequence number */ inpkt->len -= sizeof(inpkt->seqno); inpkt->seqno = ntohl(inpkt->seqno); if(replaywin) { if(inpkt->seqno != n->received_seqno + 1) { if(inpkt->seqno >= n->received_seqno + replaywin * 8) { if(n->farfuture++ < replaywin >> 2) { logger(LOG_WARNING, "Packet from %s (%s) is %d seqs in the future, dropped (%u)", n->name, n->hostname, inpkt->seqno - n->received_seqno - 1, n->farfuture); return; } logger(LOG_WARNING, "Lost %d packets from %s (%s)", inpkt->seqno - n->received_seqno - 1, n->name, n->hostname); memset(n->late, 0, replaywin); } else if (inpkt->seqno <= n->received_seqno) { if((n->received_seqno >= replaywin * 8 && inpkt->seqno <= n->received_seqno - replaywin * 8) || !(n->late[(inpkt->seqno / 8) % replaywin] & (1 << inpkt->seqno % 8))) { logger(LOG_WARNING, "Got late or replayed packet from %s (%s), seqno %d, last received %d", n->name, n->hostname, inpkt->seqno, n->received_seqno); return; } } else { for(i = n->received_seqno + 1; i < inpkt->seqno; i++) n->late[(i / 8) % replaywin] |= 1 << i % 8; } } n->farfuture = 0; n->late[(inpkt->seqno / 8) % replaywin] &= ~(1 << inpkt->seqno % 8); }
int EncryptCopyRegularFileNet(const char *source, const char *dest, off_t size, AgentConnection *conn) { int dd, blocksize = 2048, n_read = 0, plainlen, more = true, finlen, cnt = 0; int tosend, cipherlen = 0; char *buf, in[CF_BUFSIZE], out[CF_BUFSIZE], workbuf[CF_BUFSIZE], cfchangedstr[265]; unsigned char iv[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8 }; EVP_CIPHER_CTX crypto_ctx; snprintf(cfchangedstr, 255, "%s%s", CF_CHANGEDSTR1, CF_CHANGEDSTR2); if ((strlen(dest) > CF_BUFSIZE - 20)) { Log(LOG_LEVEL_ERR, "Filename too long"); return false; } unlink(dest); /* To avoid link attacks */ if ((dd = safe_open(dest, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600)) == -1) { Log(LOG_LEVEL_ERR, "Copy from server '%s' to destination '%s' failed (open: %s)", conn->this_server, dest, GetErrorStr()); unlink(dest); return false; } if (size == 0) { // No sense in copying an empty file close(dd); return true; } workbuf[0] = '\0'; EVP_CIPHER_CTX_init(&crypto_ctx); snprintf(in, CF_BUFSIZE - CF_PROTO_OFFSET, "GET dummykey %s", source); cipherlen = EncryptString(out, sizeof(out), in, strlen(in) + 1, conn->encryption_type, conn->session_key); tosend = cipherlen + CF_PROTO_OFFSET; if(tosend > sizeof(workbuf)) { ProgrammingError("EncryptCopyRegularFileNet: tosend (%d) > workbuf (%ld)", tosend, sizeof(workbuf)); } snprintf(workbuf, CF_BUFSIZE, "SGET %4d %4d", cipherlen, blocksize); memcpy(workbuf + CF_PROTO_OFFSET, out, cipherlen); /* Send proposition C0 - query */ if (SendTransaction(conn->conn_info, workbuf, tosend, CF_DONE) == -1) { Log(LOG_LEVEL_ERR, "Couldn't send data. (SendTransaction: %s)", GetErrorStr()); close(dd); return false; } buf = xmalloc(CF_BUFSIZE + sizeof(int)); bool last_write_made_hole = false; size_t n_wrote_total = 0; while (more) { if ((cipherlen = ReceiveTransaction(conn->conn_info, buf, &more)) == -1) { free(buf); return false; } cnt++; /* If the first thing we get is an error message, break. */ if (n_wrote_total == 0 && strncmp(buf + CF_INBAND_OFFSET, CF_FAILEDSTR, strlen(CF_FAILEDSTR)) == 0) { Log(LOG_LEVEL_INFO, "Network access to '%s:%s' denied", conn->this_server, source); close(dd); free(buf); return false; } if (strncmp(buf + CF_INBAND_OFFSET, cfchangedstr, strlen(cfchangedstr)) == 0) { Log(LOG_LEVEL_INFO, "Source '%s:%s' changed while copying", conn->this_server, source); close(dd); free(buf); return false; } EVP_DecryptInit_ex(&crypto_ctx, CfengineCipher(CfEnterpriseOptions()), NULL, conn->session_key, iv); if (!EVP_DecryptUpdate(&crypto_ctx, workbuf, &plainlen, buf, cipherlen)) { close(dd); free(buf); return false; } if (!EVP_DecryptFinal_ex(&crypto_ctx, workbuf + plainlen, &finlen)) { close(dd); free(buf); return false; } n_read = plainlen + finlen; bool w_ok = FileSparseWrite(dd, workbuf, n_read, &last_write_made_hole); if (!w_ok) { Log(LOG_LEVEL_ERR, "Local disk write failed copying '%s:%s' to '%s'", conn->this_server, source, dest); free(buf); unlink(dest); close(dd); conn->error = true; EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } n_wrote_total += n_read; } const bool do_sync = false; bool ret = FileSparseClose(dd, dest, do_sync, n_wrote_total, last_write_made_hole); if (!ret) { unlink(dest); free(buf); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return false; } free(buf); EVP_CIPHER_CTX_cleanup(&crypto_ctx); return true; }
static void test1(const EVP_CIPHER *c,const unsigned char *key,int kn, const unsigned char *iv,int in, const unsigned char *plaintext,int pn, const unsigned char *ciphertext,int cn, int encdec) { EVP_CIPHER_CTX ctx; unsigned char out[4096]; int outl,outl2; printf("Testing cipher %s%s\n",EVP_CIPHER_name(c), (encdec == 1 ? "(encrypt)" : (encdec == 0 ? "(decrypt)" : "(encrypt/decrypt)"))); hexdump(stdout,"Key",key,kn); if(in) hexdump(stdout,"IV",iv,in); hexdump(stdout,"Plaintext",plaintext,pn); hexdump(stdout,"Ciphertext",ciphertext,cn); if(kn != c->key_len) { fprintf(stderr,"Key length doesn't match, got %d expected %lu\n",kn, (unsigned long)c->key_len); test1_exit(5); } EVP_CIPHER_CTX_init(&ctx); if (encdec != 0) { if(!EVP_EncryptInit_ex(&ctx,c,NULL,key,iv)) { fprintf(stderr,"EncryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(10); } EVP_CIPHER_CTX_set_padding(&ctx,0); if(!EVP_EncryptUpdate(&ctx,out,&outl,plaintext,pn)) { fprintf(stderr,"Encrypt failed\n"); ERR_print_errors_fp(stderr); test1_exit(6); } if(!EVP_EncryptFinal_ex(&ctx,out+outl,&outl2)) { fprintf(stderr,"EncryptFinal failed\n"); ERR_print_errors_fp(stderr); test1_exit(7); } if(outl+outl2 != cn) { fprintf(stderr,"Ciphertext length mismatch got %d expected %d\n", outl+outl2,cn); test1_exit(8); } if(memcmp(out,ciphertext,cn)) { fprintf(stderr,"Ciphertext mismatch\n"); hexdump(stderr,"Got",out,cn); hexdump(stderr,"Expected",ciphertext,cn); test1_exit(9); } } if (encdec <= 0) { if(!EVP_DecryptInit_ex(&ctx,c,NULL,key,iv)) { fprintf(stderr,"DecryptInit failed\n"); ERR_print_errors_fp(stderr); test1_exit(11); } EVP_CIPHER_CTX_set_padding(&ctx,0); if(!EVP_DecryptUpdate(&ctx,out,&outl,ciphertext,cn)) { fprintf(stderr,"Decrypt failed\n"); ERR_print_errors_fp(stderr); test1_exit(6); } if(!EVP_DecryptFinal_ex(&ctx,out+outl,&outl2)) { fprintf(stderr,"DecryptFinal failed\n"); ERR_print_errors_fp(stderr); test1_exit(7); } if(outl+outl2 != pn) { fprintf(stderr,"Plaintext length mismatch got %d expected %d\n", outl+outl2,pn); test1_exit(8); } if(memcmp(out,plaintext,pn)) { fprintf(stderr,"Plaintext mismatch\n"); hexdump(stderr,"Got",out,pn); hexdump(stderr,"Expected",plaintext,pn); test1_exit(9); } } EVP_CIPHER_CTX_cleanup(&ctx); printf("\n"); }
static int import_dkek_share(sc_card_t *card, const char *inf, int iter, const char *password, int num_of_password_shares) { sc_cardctl_sc_hsm_dkek_t dkekinfo; EVP_CIPHER_CTX ctx; FILE *in = NULL; u8 filebuff[64],key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH],outbuff[64]; char *pwd = NULL; int r, outlen, pwdlen; if (inf == NULL) { fprintf(stderr, "No file name specified for DKEK share\n"); return -1; } in = fopen(inf, "rb"); if (in == NULL) { perror(inf); return -1; } if (fread(filebuff, 1, sizeof(filebuff), in) != sizeof(filebuff)) { perror(inf); fclose(in); return -1; } fclose(in); if (memcmp(filebuff, magic, sizeof(magic) - 1)) { fprintf(stderr, "File %s is not a DKEK share\n", inf); return -1; } if (password == NULL) { if (num_of_password_shares == -1) { printf("Enter password to decrypt DKEK share : "); util_getpass(&pwd, NULL, stdin); pwdlen = strlen(pwd); printf("\n"); } else { r = recreate_password_from_shares(&pwd, &pwdlen, num_of_password_shares); if (r < 0) { return -1; } } } else { pwd = (char *) password; pwdlen = strlen(password); } printf("Deciphering DKEK share, please wait...\n"); EVP_BytesToKey(EVP_aes_256_cbc(), EVP_md5(), filebuff + 8, (u8 *)pwd, pwdlen, iter, key, iv); OPENSSL_cleanse(pwd, strlen(pwd)); if (password == NULL) { free(pwd); } EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, EVP_aes_256_cbc(), NULL, key, iv); if (!EVP_DecryptUpdate(&ctx, outbuff, &outlen, filebuff + 16, sizeof(filebuff) - 16)) { fprintf(stderr, "Error decrypting DKEK share. Password correct ?\n"); return -1; } if (!EVP_DecryptFinal_ex(&ctx, outbuff + outlen, &r)) { fprintf(stderr, "Error decrypting DKEK share. Password correct ?\n"); return -1; } memset(&dkekinfo, 0, sizeof(dkekinfo)); memcpy(dkekinfo.dkek_share, outbuff, sizeof(dkekinfo.dkek_share)); dkekinfo.importShare = 1; OPENSSL_cleanse(outbuff, sizeof(outbuff)); r = sc_card_ctl(card, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, (void *)&dkekinfo); OPENSSL_cleanse(&dkekinfo.dkek_share, sizeof(dkekinfo.dkek_share)); EVP_CIPHER_CTX_cleanup(&ctx); if (r == SC_ERROR_INS_NOT_SUPPORTED) { // Not supported or not initialized for key shares fprintf(stderr, "Not supported by card or card not initialized for key share usage\n"); return -1; } if (r < 0) { fprintf(stderr, "sc_card_ctl(*, SC_CARDCTL_SC_HSM_IMPORT_DKEK_SHARE, *) failed with %s\n", sc_strerror(r)); return -1; } printf("DKEK share imported\n"); print_dkek_info(&dkekinfo); return 0; }
// generate keys static int cryptoSetKeys(struct s_crypto *ctxs, const int count, const unsigned char *secret_buf, const int secret_len, const unsigned char *nonce_buf, const int nonce_len) { int cur_key_len; unsigned char cur_key[EVP_MAX_MD_SIZE]; int seed_key_len; unsigned char seed_key[EVP_MAX_MD_SIZE]; const EVP_MD *keygen_md = EVP_sha512(); const EVP_MD *out_md = EVP_sha256(); const EVP_CIPHER *out_cipher = EVP_aes_256_cbc(); const int key_size = EVP_CIPHER_key_length(out_cipher); HMAC_CTX hmac_ctx; int16_t i; unsigned char in[2]; int j,k; // setup hmac as the pseudorandom function HMAC_CTX_init(&hmac_ctx); // calculate seed key HMAC_Init_ex(&hmac_ctx, nonce_buf, nonce_len, keygen_md, NULL); HMAC_Update(&hmac_ctx, secret_buf, secret_len); HMAC_Final(&hmac_ctx, seed_key, (unsigned int *)&seed_key_len); // calculate derived keys HMAC_Init_ex(&hmac_ctx, seed_key, seed_key_len, keygen_md, NULL); HMAC_Update(&hmac_ctx, nonce_buf, nonce_len); HMAC_Final(&hmac_ctx, cur_key, (unsigned int *)&cur_key_len); i = 0; j = 0; k = 0; while(k < count) { // calculate next key utilWriteInt16(in, i); HMAC_Init_ex(&hmac_ctx, NULL, -1, NULL, NULL); HMAC_Update(&hmac_ctx, cur_key, cur_key_len); HMAC_Update(&hmac_ctx, nonce_buf, nonce_len); HMAC_Update(&hmac_ctx, in, 2); HMAC_Final(&hmac_ctx, cur_key, (unsigned int *)&cur_key_len); if(cur_key_len < key_size) return 0; // check if key is long enough switch(j) { case 1: // save this key as the decryption and encryption key if(!EVP_EncryptInit_ex(&ctxs[k].enc_ctx, out_cipher, NULL, cur_key, NULL)) return 0; if(!EVP_DecryptInit_ex(&ctxs[k].dec_ctx, out_cipher, NULL, cur_key, NULL)) return 0; break; case 2: // save this key as the hmac key HMAC_Init_ex(&ctxs[k].hmac_ctx, cur_key, cur_key_len, out_md, NULL); break; default: // throw this key away break; } if(j > 3) { j = 0; k++; } j++; i++; } // clean up HMAC_CTX_cleanup(&hmac_ctx); return 1; }
int TLSTicketKeyManager::processTicket(SSL*, unsigned char* keyName, unsigned char* iv, EVP_CIPHER_CTX* cipherCtx, HMAC_CTX* hmacCtx, int encrypt) { uint8_t salt[kTLSTicketKeySaltLen]; uint8_t* saltptr = nullptr; uint8_t output[SHA256_DIGEST_LENGTH]; uint8_t* hmacKey = nullptr; uint8_t* aesKey = nullptr; TLSTicketKeySource* key = nullptr; int result = 0; if (encrypt) { key = findEncryptionKey(); if (key == nullptr) { // no keys available to encrypt VLOG(2) << "No TLS ticket key found"; return -1; } VLOG(4) << "Encrypting new ticket with key name=" << SSLUtil::hexlify(key->keyName_); // Get a random salt and write out key name if (RAND_bytes(salt, (int)sizeof(salt)) != 1 && ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_RAND) { ERR_get_error(); } memcpy(keyName, key->keyName_.data(), kTLSTicketKeyNameLen); memcpy(keyName + kTLSTicketKeyNameLen, salt, kTLSTicketKeySaltLen); // Create the unique keys by hashing with the salt makeUniqueKeys(key->keySource_, sizeof(key->keySource_), salt, output); // This relies on the fact that SHA256 has 32 bytes of output // and that AES-128 keys are 16 bytes hmacKey = output; aesKey = output + SHA256_DIGEST_LENGTH / 2; // Initialize iv and cipher/mac CTX if (RAND_bytes(iv, AES_BLOCK_SIZE) != 1 && ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_RAND) { ERR_get_error(); } HMAC_Init_ex(hmacCtx, hmacKey, SHA256_DIGEST_LENGTH / 2, EVP_sha256(), nullptr); EVP_EncryptInit_ex(cipherCtx, EVP_aes_128_cbc(), nullptr, aesKey, iv); result = 1; } else { key = findDecryptionKey(keyName); if (key == nullptr) { // no ticket found for decryption - will issue a new ticket if (VLOG_IS_ON(4)) { string skeyName((char *)keyName, kTLSTicketKeyNameLen); VLOG(4) << "Can't find ticket key with name=" << SSLUtil::hexlify(skeyName)<< ", will generate new ticket"; } result = 0; } else { VLOG(4) << "Decrypting ticket with key name=" << SSLUtil::hexlify(key->keyName_); // Reconstruct the unique key via the salt saltptr = keyName + kTLSTicketKeyNameLen; makeUniqueKeys(key->keySource_, sizeof(key->keySource_), saltptr, output); hmacKey = output; aesKey = output + SHA256_DIGEST_LENGTH / 2; // Initialize cipher/mac CTX HMAC_Init_ex(hmacCtx, hmacKey, SHA256_DIGEST_LENGTH / 2, EVP_sha256(), nullptr); EVP_DecryptInit_ex(cipherCtx, EVP_aes_128_cbc(), nullptr, aesKey, iv); result = 1; } } // result records whether a ticket key was found to decrypt this ticket, // not wether the session was re-used. if (stats_) { stats_->recordTLSTicket(encrypt, result); } return result; }
Blob CKey::decryptECIES (CKey& otherKey, Blob const& ciphertext) { // minimum ciphertext = IV + HMAC + 1 block if (ciphertext.size () < ((2 * ECIES_ENC_BLK_SIZE) + ECIES_HMAC_SIZE) ) throw std::runtime_error ("ciphertext too short"); // extract IV ECIES_ENC_IV_TYPE iv; memcpy (iv.begin (), & (ciphertext.front ()), ECIES_ENC_BLK_SIZE); // begin decrypting EVP_CIPHER_CTX ctx; EVP_CIPHER_CTX_init (&ctx); ECIES_ENC_KEY_TYPE secret; ECIES_HMAC_KEY_TYPE hmacKey; getECIESSecret (otherKey, secret, hmacKey); if (EVP_DecryptInit_ex (&ctx, ECIES_ENC_ALGO, NULL, secret.begin (), iv.begin ()) != 1) { secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); throw std::runtime_error ("unable to init cipher"); } // decrypt mac ECIES_HMAC_TYPE hmac; int outlen = ECIES_HMAC_SIZE; if ( (EVP_DecryptUpdate (&ctx, hmac.begin (), &outlen, & (ciphertext.front ()) + ECIES_ENC_BLK_SIZE, ECIES_HMAC_SIZE + 1) != 1) || (outlen != ECIES_HMAC_SIZE) ) { secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); throw std::runtime_error ("unable to extract hmac"); } // decrypt plaintext (after IV and encrypted mac) Blob plaintext (ciphertext.size () - ECIES_HMAC_SIZE - ECIES_ENC_BLK_SIZE); outlen = plaintext.size (); if (EVP_DecryptUpdate (&ctx, & (plaintext.front ()), &outlen, & (ciphertext.front ()) + ECIES_ENC_BLK_SIZE + ECIES_HMAC_SIZE + 1, ciphertext.size () - ECIES_ENC_BLK_SIZE - ECIES_HMAC_SIZE - 1) != 1) { secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); throw std::runtime_error ("unable to extract plaintext"); } // decrypt padding int flen = 0; if (EVP_DecryptFinal (&ctx, & (plaintext.front ()) + outlen, &flen) != 1) { secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); throw std::runtime_error ("plaintext had bad padding"); } plaintext.resize (flen + outlen); // verify integrity if (hmac != makeHMAC (hmacKey, plaintext)) { secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); throw std::runtime_error ("plaintext had bad hmac"); } secret.zero (); hmacKey.zero (); EVP_CIPHER_CTX_cleanup (&ctx); return plaintext; }
static bool decrypt(const char *privkeyfile, const char *keyfile, const char *input, const char *output) { uint8_t buf[KERNELDUMP_BUFFER_SIZE], key[KERNELDUMP_KEY_MAX_SIZE]; EVP_CIPHER_CTX ctx; const EVP_CIPHER *cipher; FILE *fp; struct kerneldumpkey *kdk; RSA *privkey; int ifd, kfd, ofd, olen, privkeysize; ssize_t bytes; pid_t pid; PJDLOG_ASSERT(privkeyfile != NULL); PJDLOG_ASSERT(keyfile != NULL); PJDLOG_ASSERT(input != NULL); PJDLOG_ASSERT(output != NULL); privkey = NULL; /* * Decrypt a core dump in a child process so we can unlink a partially * decrypted core if the child process fails. */ pid = fork(); if (pid == -1) { pjdlog_errno(LOG_ERR, "Unable to create child process"); return (false); } if (pid > 0) return (wait_for_process(pid) == 0); kfd = open(keyfile, O_RDONLY); if (kfd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", keyfile); goto failed; } ifd = open(input, O_RDONLY); if (ifd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", input); goto failed; } ofd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0600); if (ofd == -1) { pjdlog_errno(LOG_ERR, "Unable to open %s", output); goto failed; } fp = fopen(privkeyfile, "r"); if (fp == NULL) { pjdlog_errno(LOG_ERR, "Unable to open %s", privkeyfile); goto failed; } if (cap_enter() < 0 && errno != ENOSYS) { pjdlog_errno(LOG_ERR, "Unable to enter capability mode"); goto failed; } privkey = RSA_new(); if (privkey == NULL) { pjdlog_error("Unable to allocate an RSA structure: %s", ERR_error_string(ERR_get_error(), NULL)); goto failed; } EVP_CIPHER_CTX_init(&ctx); kdk = read_key(kfd); close(kfd); if (kdk == NULL) goto failed; privkey = PEM_read_RSAPrivateKey(fp, &privkey, NULL, NULL); fclose(fp); if (privkey == NULL) { pjdlog_error("Unable to read data from %s.", privkeyfile); goto failed; } privkeysize = RSA_size(privkey); if (privkeysize != (int)kdk->kdk_encryptedkeysize) { pjdlog_error("RSA modulus size mismatch: equals %db and should be %ub.", 8 * privkeysize, 8 * kdk->kdk_encryptedkeysize); goto failed; } switch (kdk->kdk_encryption) { case KERNELDUMP_ENC_AES_256_CBC: cipher = EVP_aes_256_cbc(); break; default: pjdlog_error("Invalid encryption algorithm."); goto failed; } if (RSA_private_decrypt(kdk->kdk_encryptedkeysize, kdk->kdk_encryptedkey, key, privkey, RSA_PKCS1_PADDING) != sizeof(key)) { pjdlog_error("Unable to decrypt key: %s", ERR_error_string(ERR_get_error(), NULL)); goto failed; } RSA_free(privkey); privkey = NULL; EVP_DecryptInit_ex(&ctx, cipher, NULL, key, kdk->kdk_iv); EVP_CIPHER_CTX_set_padding(&ctx, 0); explicit_bzero(key, sizeof(key)); do { bytes = read(ifd, buf, sizeof(buf)); if (bytes < 0) { pjdlog_errno(LOG_ERR, "Unable to read data from %s", input); goto failed; } else if (bytes == 0) { break; } if (bytes > 0) { if (EVP_DecryptUpdate(&ctx, buf, &olen, buf, bytes) == 0) { pjdlog_error("Unable to decrypt core."); goto failed; } } else { if (EVP_DecryptFinal_ex(&ctx, buf, &olen) == 0) { pjdlog_error("Unable to decrypt core."); goto failed; } } if (olen == 0) continue; if (write(ofd, buf, olen) != olen) { pjdlog_errno(LOG_ERR, "Unable to write data to %s", output); goto failed; } } while (bytes > 0); explicit_bzero(buf, sizeof(buf)); EVP_CIPHER_CTX_cleanup(&ctx); exit(0); failed: explicit_bzero(key, sizeof(key)); explicit_bzero(buf, sizeof(buf)); RSA_free(privkey); EVP_CIPHER_CTX_cleanup(&ctx); exit(1); }
int libCryptoProcessorInit(TProcessingModule *ProcMod, const char *Args) { int result=FALSE; #ifdef HAVE_LIBSSL libCryptoProcessorData *Data; EVP_CIPHER_CTX *ctx; char *CipherList[]={"blowfish","rc2","rc4","rc5","des","desx","cast","idea","aes","aes-256",NULL}; int val; char *Tempstr=NULL; val=MatchTokenFromList(ProcMod->Name,CipherList,0); if (val==-1) return(FALSE); if (! libCryptoCipherAvailable(val)) return(FALSE); Data=(libCryptoProcessorData *) calloc(1,sizeof(libCryptoProcessorData)); //Tempstr here holds the cipher name InitialiseEncryptionComponents(Args, &Tempstr, &Data->InputVector, &Data->InputVectorLen, & Data->Key, &Data->KeyLen,&ProcMod->Flags); if (StrLen(ProcMod->Name)==0) ProcMod->Name=CopyStr(ProcMod->Name,Tempstr); switch(val) { /* case CI_NONE: Data->Cipher=EVP_enc_null(); break; */ case CI_BLOWFISH: #ifdef HAVE_EVP_BF_CBC Data->Cipher=EVP_bf_cbc(); #endif break; case CI_RC2: #ifdef HAVE_EVP_RC2_CBC Data->Cipher=EVP_rc2_cbc(); #endif break; case CI_RC4: #ifdef HAVE_EVP_RC4_CBC Data->Cipher=EVP_rc4(); #endif break; case CI_RC5: #ifdef HAVE_EVP_RC5_32_12_16_CBC //Data->Cipher=EVP_rc5_32_12_16_cbc(); #endif break; case CI_DES: #ifdef HAVE_EVP_DES_CBC Data->Cipher=EVP_des_cbc(); #endif break; case CI_DESX: #ifdef HAVE_EVP_DESX_CBC Data->Cipher=EVP_desx_cbc(); #endif break; case CI_CAST: #ifdef HAVE_EVP_CAST5_CBC Data->Cipher=EVP_cast5_cbc(); #endif break; case CI_IDEA: #ifdef HAVE_EVP_IDEA_CBC Data->Cipher=EVP_idea_cbc(); #endif break; case CI_AES: #ifdef HAVE_EVP_AES_128_CBC Data->Cipher=EVP_aes_128_cbc(); #endif break; case CI_AES_256: #ifdef HAVE_EVP_AES_256_CBC Data->Cipher=EVP_aes_256_cbc(); #endif break; } if (Data->Cipher) { Data->enc_ctx=(EVP_CIPHER_CTX *) calloc(1,sizeof(EVP_CIPHER_CTX)); Data->dec_ctx=(EVP_CIPHER_CTX *) calloc(1,sizeof(EVP_CIPHER_CTX)); EVP_CIPHER_CTX_init(Data->enc_ctx); EVP_CIPHER_CTX_init(Data->dec_ctx); Data->BlockSize=EVP_CIPHER_block_size(Data->Cipher); EVP_EncryptInit_ex(Data->enc_ctx,Data->Cipher,NULL,Data->Key,Data->InputVector); EVP_DecryptInit_ex(Data->dec_ctx,Data->Cipher,NULL,Data->Key,Data->InputVector); if (ProcMod->Flags & DPM_NOPAD_DATA) EVP_CIPHER_CTX_set_padding(Data->enc_ctx,FALSE); ProcMod->Data=Data; result=TRUE; DataProcessorSetValue(ProcMod,"Cipher",Tempstr); Tempstr=FormatStr(Tempstr,"%d",Data->BlockSize); DataProcessorSetValue(ProcMod,"BlockSize",Tempstr); } DestroyString(Tempstr); #endif return(result); }
std::vector<unsigned char> openssl_decrypt (unsigned char *key, unsigned char *iv, unsigned char *encryptedData, int encryptedLength) { // Initialisation EVP_CIPHER_CTX *cryptCtx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(cryptCtx); int decryptedLength = 0; int allocateSize = encryptedLength * sizeof(unsigned char); int lastDecryptLength = 0; unsigned char *decryptedData = (unsigned char *) malloc (allocateSize); memset(decryptedData, 0x00, allocateSize); int decryptResult = EVP_DecryptInit_ex(cryptCtx, EVP_aes_256_cbc(), NULL, key, iv); // EVP_DecryptInit_ex returns 1 if it succeeded. if (decryptResult == 1) { decryptResult = EVP_DecryptUpdate(cryptCtx, decryptedData, &decryptedLength, encryptedData, encryptedLength); // Cleanup if (decryptResult == 1) { // Stick the final data at the end of the last // decrypted data. EVP_DecryptFinal_ex(cryptCtx, decryptedData + decryptedLength, &lastDecryptLength); decryptedLength = decryptedLength + lastDecryptLength; //decryptedData[decryptedLength - 1] = ' '; } else { __android_log_write(ANDROID_LOG_ERROR, "JNI_DEC", "EVP_DeccryptUpdate failure."); } } else { __android_log_write(ANDROID_LOG_ERROR, "JNI_DEC", "EVP_DecryptInit_ex failure."); } EVP_CIPHER_CTX_free(cryptCtx); EVP_cleanup(); std::vector<unsigned char> decVector(decryptedLength); int i = 0; for(i=0;i<decryptedLength;i++){ //decVector.push_back(decryptedData[i]); decVector[i] = decryptedData[i]; } return decVector; }
static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen, const unsigned char *sess_id, int sesslen, SSL_SESSION **psess) { SSL_SESSION *sess; unsigned char *sdec; const unsigned char *p; int slen, mlen, renew_ticket = 0; unsigned char tick_hmac[EVP_MAX_MD_SIZE]; HMAC_CTX hctx; EVP_CIPHER_CTX ctx; SSL_CTX *tctx = s->initial_ctx; /* Need at least keyname + iv + some encrypted data */ if (eticklen < 48) goto tickerr; /* Initialize session ticket encryption and HMAC contexts */ HMAC_CTX_init(&hctx); EVP_CIPHER_CTX_init(&ctx); if (tctx->tlsext_ticket_key_cb) { unsigned char *nctick = (unsigned char *)etick; int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16, &ctx, &hctx, 0); if (rv < 0) return -1; if (rv == 0) goto tickerr; if (rv == 2) renew_ticket = 1; } else { /* Check key name matches */ if (memcmp(etick, tctx->tlsext_tick_key_name, 16)) goto tickerr; HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(), NULL); EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, tctx->tlsext_tick_aes_key, etick + 16); } /* Attempt to process session ticket, first conduct sanity and * integrity checks on ticket. */ mlen = HMAC_size(&hctx); if (mlen < 0) { EVP_CIPHER_CTX_cleanup(&ctx); return -1; } eticklen -= mlen; /* Check HMAC of encrypted ticket */ HMAC_Update(&hctx, etick, eticklen); HMAC_Final(&hctx, tick_hmac, NULL); HMAC_CTX_cleanup(&hctx); if (memcmp(tick_hmac, etick + eticklen, mlen)) goto tickerr; /* Attempt to decrypt session data */ /* Move p after IV to start of encrypted ticket, update length */ p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx); eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx); sdec = OPENSSL_malloc(eticklen); if (!sdec) { EVP_CIPHER_CTX_cleanup(&ctx); return -1; } EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen); if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0) goto tickerr; slen += mlen; EVP_CIPHER_CTX_cleanup(&ctx); p = sdec; sess = d2i_SSL_SESSION(NULL, &p, slen); OPENSSL_free(sdec); if (sess) { /* The session ID if non-empty is used by some clients to * detect that the ticket has been accepted. So we copy it to * the session structure. If it is empty set length to zero * as required by standard. */ if (sesslen) memcpy(sess->session_id, sess_id, sesslen); sess->session_id_length = sesslen; *psess = sess; s->tlsext_ticket_expected = renew_ticket; return 1; } /* If session decrypt failure indicate a cache miss and set state to * send a new ticket */ tickerr: s->tlsext_ticket_expected = 1; return 0; }
int crypto_decrypt_file(FILE * in, FILE * out) { EVP_CIPHER_CTX ctx; uint8_t ibuf[CRYPTO_BUFFER_SIZE]; uint8_t obuf[CRYPTO_BUFFER_SIZE]; uint8_t iv[IV_SIZE]; uint8_t tag[GCM_TAG_SIZE]; uint8_t version; size_t r, w; off_t sz; int len; int ret = 0; struct stat sb; /* input file too small to be an encrypted file */ if (fstat(fileno(in), &sb) < 0) return 0; if (sb.st_size <= (off_t) (sizeof version + sizeof tag + sizeof iv)) return 0; sz = sb.st_size; /* extract tag */ if (fseek(in, -sizeof(tag), SEEK_END) == -1) return 0; if ((r = fread(tag, 1, sizeof tag, in)) != sizeof tag) return 0; if (fseek(in, 0, SEEK_SET) == -1) return 0; /* extract version */ if ((r = fread(&version, 1, sizeof version, in)) != sizeof version) return 0; if (version != API_VERSION) return 0; /* extract IV */ memset(iv, 0, sizeof iv); if ((r = fread(iv, 1, sizeof iv, in)) != sizeof iv) return 0; /* real ciphertext length */ sz -= sizeof version; sz -= sizeof iv; sz -= sizeof tag; EVP_CIPHER_CTX_init(&ctx); EVP_DecryptInit_ex(&ctx, EVP_aes_256_gcm(), NULL, cp.key, iv); /* set expected tag */ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, sizeof tag, tag); /* decrypt until end of ciphertext */ while (sz) { if (sz > CRYPTO_BUFFER_SIZE) r = fread(ibuf, 1, CRYPTO_BUFFER_SIZE, in); else r = fread(ibuf, 1, sz, in); if (!r) break; if (!EVP_DecryptUpdate(&ctx, obuf, &len, ibuf, r)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; sz -= r; } if (ferror(in)) goto end; /* finalize, write last chunk if any and perform authentication check */ if (!EVP_DecryptFinal_ex(&ctx, obuf, &len)) goto end; if (len && (w = fwrite(obuf, len, 1, out)) != 1) goto end; fflush(out); ret = 1; end: EVP_CIPHER_CTX_cleanup(&ctx); return ret; }
int rsa_decrypt (const char *const key_name, int public_key, void *input, int ilen, void **output, int *olen, int log_error_level) { vkprintf (3, "rsa_decrypt (key_name = %s, ilen = %d)\n", key_name, ilen); int err = 0, rsa_size = -1; void *b = NULL; *output = NULL; if (ilen < 4) { vkprintf (log_error_level, "Input too short (ilen = %d).\n", ilen); return -3; } memcpy (&rsa_size, input, 4); if (ilen < 4 + rsa_size + 32) { vkprintf (log_error_level, "Input too short (ilen = %d).\n", ilen); return -3; } FILE *f = fopen (key_name, "rb"); if (f == NULL) { vkprintf (log_error_level, "Couldn't open key file: %s\n", key_name); return -1; } RSA *pubKey = NULL; if (public_key) { if (!PEM_read_RSA_PUBKEY (f, &pubKey, NULL, NULL)) { vkprintf (log_error_level, "PEM_read_RSA_PUBKEY: failed.\n"); err = -2; goto clean; } } else { RSA *privKey = PEM_read_RSAPrivateKey (f, NULL, NULL, NULL); if (privKey == NULL) { vkprintf (log_error_level, "PEM_read_RSA_PUBKEY: failed.\n"); err = -7; goto clean; } pubKey = RSAPublicKey_dup (privKey); assert (pubKey != NULL); RSA_free (privKey); } assert (pubKey != NULL); fclose (f); f = NULL; vkprintf (3, "rsa_decrypt: read key - ok!\n"); if (rsa_size != RSA_size (pubKey)) { vkprintf (log_error_level, "Illegal key size = %d.\n", RSA_size (pubKey)); err = -4; goto clean; } b = malloc (rsa_size); if (b == NULL) { vkprintf (log_error_level, "malloc (%d) fail. %m\n", rsa_size); err = -8; goto clean; } if (!RSA_public_decrypt (rsa_size, input + 4, b, pubKey, RSA_PKCS1_PADDING)) { vkprintf (log_error_level, "RSA_public_decrypt failed.\n"); err = -5; goto clean; } unsigned char key[32], iv[32]; memcpy (key, b, 32); free (b); b = NULL; memcpy (iv, input + 4 + rsa_size, 32); int aes_cipher_len = ilen - (4 + rsa_size + 32); void *a = malloc (aes_cipher_len); if (a == NULL) { vkprintf (log_error_level, "malloc (%d) fail. %m\n", aes_cipher_len); err = -9; goto clean; } *output = a; int p_len = 0; EVP_CIPHER_CTX e; EVP_CIPHER_CTX_init (&e); EVP_DecryptInit_ex (&e, EVP_aes_256_cbc(), NULL, key, iv); EVP_DecryptUpdate (&e, a, &p_len, input + 4 + rsa_size + 32, aes_cipher_len); int f_len = 0; EVP_DecryptFinal_ex (&e, input + 4 + rsa_size + 32 + p_len, &f_len); vkprintf (3, "p_len = %d, f_len = %d\n", p_len, f_len); *olen = p_len + f_len; EVP_CIPHER_CTX_cleanup (&e); clean: if (f != NULL) { fclose (f); } if (pubKey) { RSA_free (pubKey); } if (b) { free (b); } return err; }
bool AES_GCM_Decrypt(COSE_Enveloped * pcose, const byte * pbKey, int cbKey, const byte * pbCrypto, size_t cbCrypto, const byte * pbAuthData, size_t cbAuthData, cose_errback * perr) { EVP_CIPHER_CTX ctx; int cbOut; byte * rgbOut = NULL; int outl = 0; byte rgbIV[15] = { 0 }; const cn_cbor * pIV = NULL; const EVP_CIPHER * cipher; #ifdef USE_CBOR_CONTEXT cn_cbor_context * context = &pcose->m_message.m_allocContext; #endif int TSize = 128 / 8; assert(perr != NULL); EVP_CIPHER_CTX_init(&ctx); // Setup the IV/Nonce and put it into the message pIV = _COSE_map_get_int(&pcose->m_message, COSE_Header_IV, COSE_BOTH, NULL); if ((pIV == NULL) || (pIV->type != CN_CBOR_BYTES)) { perr->err = COSE_ERR_INVALID_PARAMETER; errorReturn: if (rgbOut != NULL) COSE_FREE(rgbOut, context); EVP_CIPHER_CTX_cleanup(&ctx); return false; } CHECK_CONDITION(pIV->length == 96/8, COSE_ERR_INVALID_PARAMETER); memcpy(rgbIV, pIV->v.str, pIV->length); // Setup and run the OpenSSL code switch (cbKey) { case 128 / 8: cipher = EVP_aes_128_gcm(); break; case 192 / 8: cipher = EVP_aes_192_gcm(); break; case 256 / 8: cipher = EVP_aes_256_gcm(); break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); break; } // Do the setup for OpenSSL CHECK_CONDITION(EVP_DecryptInit_ex(&ctx, cipher, NULL, NULL, NULL), COSE_ERR_DECRYPT_FAILED); CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_CCM_SET_TAG, TSize, (void *)&pbCrypto[cbCrypto - TSize]), COSE_ERR_DECRYPT_FAILED); CHECK_CONDITION(EVP_DecryptInit(&ctx, 0, pbKey, rgbIV), COSE_ERR_DECRYPT_FAILED); // Pus in the AAD CHECK_CONDITION(EVP_DecryptUpdate(&ctx, NULL, &outl, pbAuthData, (int) cbAuthData), COSE_ERR_DECRYPT_FAILED); // cbOut = (int)cbCrypto - TSize; rgbOut = (byte *)COSE_CALLOC(cbOut, 1, context); CHECK_CONDITION(rgbOut != NULL, COSE_ERR_OUT_OF_MEMORY); // Process content CHECK_CONDITION(EVP_DecryptUpdate(&ctx, rgbOut, &cbOut, pbCrypto, (int)cbCrypto - TSize), COSE_ERR_DECRYPT_FAILED); // Process Tag CHECK_CONDITION(EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_GCM_SET_TAG, TSize, (byte *)pbCrypto + cbCrypto - TSize), COSE_ERR_DECRYPT_FAILED); // Check the result CHECK_CONDITION(EVP_DecryptFinal(&ctx, rgbOut + cbOut, &cbOut), COSE_ERR_DECRYPT_FAILED); EVP_CIPHER_CTX_cleanup(&ctx); pcose->pbContent = rgbOut; pcose->cbContent = cbOut; return true; }
sgx_status_t sgx_rijndael128GCM_decrypt(const sgx_aes_gcm_128bit_key_t *p_key, const uint8_t *p_src, uint32_t src_len, uint8_t *p_dst, const uint8_t *p_iv, uint32_t iv_len, const uint8_t *p_aad, uint32_t aad_len, const sgx_aes_gcm_128bit_tag_t *p_in_mac) { uint8_t l_tag[SGX_AESGCM_MAC_SIZE]; if ((src_len >= INT_MAX) || (aad_len >= INT_MAX) || (p_key == NULL) || ((src_len > 0) && (p_dst == NULL)) || ((src_len > 0) && (p_src == NULL)) || (p_in_mac == NULL) || (iv_len != SGX_AESGCM_IV_SIZE) || ((aad_len > 0) && (p_aad == NULL)) || (p_iv == NULL) || ((p_src == NULL) && (p_aad == NULL))) { return SGX_ERROR_INVALID_PARAMETER; } int len = 0; sgx_status_t ret = SGX_ERROR_UNEXPECTED; EVP_CIPHER_CTX * pState = NULL; // Autenthication Tag returned by Decrypt to be compared with Tag created during seal // memset_s(&l_tag, SGX_AESGCM_MAC_SIZE, 0, SGX_AESGCM_MAC_SIZE); memcpy(l_tag, p_in_mac, SGX_AESGCM_MAC_SIZE); do { // Create and initialise the context // if (!(pState = EVP_CIPHER_CTX_new())) { ret = SGX_ERROR_OUT_OF_MEMORY; break; } // Initialise decrypt, key and IV // if (!EVP_DecryptInit_ex(pState, EVP_aes_128_gcm(), NULL, (unsigned char*)p_key, p_iv)) { break; } // Provide AAD data if exist // if (NULL != p_aad) { if (!EVP_DecryptUpdate(pState, NULL, &len, p_aad, aad_len)) { break; } } // Decrypt message, obtain the plaintext output // if (!EVP_DecryptUpdate(pState, p_dst, &len, p_src, src_len)) { break; } // Update expected tag value // if (!EVP_CIPHER_CTX_ctrl(pState, EVP_CTRL_GCM_SET_TAG, SGX_AESGCM_MAC_SIZE, l_tag)) { break; } // Finalise the decryption. A positive return value indicates success, // anything else is a failure - the plaintext is not trustworthy. // if (EVP_DecryptFinal_ex(pState, p_dst + len, &len) <= 0) { ret = SGX_ERROR_MAC_MISMATCH; break; } ret = SGX_SUCCESS; } while (0); // Clean up and return // if (pState != NULL) { EVP_CIPHER_CTX_free(pState); } memset_s(&l_tag, SGX_AESGCM_MAC_SIZE, 0, SGX_AESGCM_MAC_SIZE); return ret; }
static void make_stream (HwpHWP5File *file, GError **error) { GsfInput *input = NULL; GsfInfile *ole = GSF_INFILE (file->priv->olefile); gint n_root_entry = gsf_infile_num_children (ole); if (n_root_entry < 1) { g_set_error_literal (error, HWP_FILE_ERROR, HWP_FILE_ERROR_INVALID, "invalid hwp file"); return; } /* 우선 순위에 따라 스트림을 만든다 */ input = gsf_infile_child_by_name (ole, "FileHeader"); if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1) { file->file_header_stream = input; input = NULL; parse_file_header (file); } else { goto FAIL; } input = gsf_infile_child_by_name (ole, "DocInfo"); if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1) { if (file->is_compress) { GInputStream *gis; GZlibDecompressor *zd; GInputStream *cis; gis = (GInputStream *) gsf_input_stream_new (input); zd = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW); cis = g_converter_input_stream_new (gis, (GConverter *) zd); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE); file->doc_info_stream = cis; g_object_unref (zd); g_object_unref (gis); input = NULL; } else { file->doc_info_stream = (GInputStream *) gsf_input_stream_new (input); } } else { goto FAIL; } if (!file->is_distribute) input = gsf_infile_child_by_name (ole, "BodyText"); else input = gsf_infile_child_by_name (ole, "ViewText"); if (input) { for (gint i = 0; i < gsf_infile_num_children (GSF_INFILE (input)); i++) { GsfInput *section = gsf_infile_child_by_name (GSF_INFILE (input), g_strdup_printf("Section%d", i)); if (gsf_infile_num_children (GSF_INFILE (section)) != -1) { if (GSF_IS_INPUT (section)) g_object_unref (section); g_set_error_literal (error, HWP_FILE_ERROR, HWP_FILE_ERROR_INVALID, "invalid hwp file"); return; } if (file->is_distribute) { guint8 *data = g_malloc0 (256); gsf_input_read (section, 4, NULL); gsf_input_read (section, 256, data); guint32 seed = GSF_LE_GET_GUINT32 (data); msvc_srand (seed); gint n = 0, val = 0, offset; for (guint i = 0; i < 256; i++) { if (n == 0) { val = msvc_rand() & 0xff; n = (msvc_rand() & 0xf) + 1; } data[i] ^= val; n--; } offset = 4 + (seed & 0xf); gchar *key = g_malloc0 (16); memcpy (key, (const gchar *) data + offset, 16); #ifdef HWP_ENABLE_DEBUG gchar *sha1 = g_convert ((const gchar *) data + offset, 80, "UTF-8", "UTF-16LE", NULL, NULL, error); printf ("sha1: %s\n", sha1); printf ("key: %s\n", key); g_free (sha1); #endif g_free (data); EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new (); EVP_CIPHER_CTX_init (ctx); EVP_DecryptInit_ex (ctx, EVP_aes_128_ecb(), NULL, (unsigned char *) key, NULL); g_free (key); EVP_CIPHER_CTX_set_padding(ctx, 0); /* no padding */ gsf_off_t encrypted_data_len = gsf_input_remaining (section); guint8 const *encrypted_data = gsf_input_read (section, encrypted_data_len, NULL); guint8 *decrypted_data = g_malloc (encrypted_data_len); int decrypted_data_len, len; EVP_DecryptUpdate (ctx, decrypted_data, &len, encrypted_data, encrypted_data_len); decrypted_data_len = len; EVP_DecryptFinal_ex (ctx, decrypted_data + len, &len); decrypted_data_len += len; EVP_CIPHER_CTX_free (ctx); g_object_unref (section); section = gsf_input_memory_new (decrypted_data, decrypted_data_len, TRUE); } if (file->is_compress) { GInputStream *gis; GZlibDecompressor *zd; GInputStream *cis; gis = (GInputStream *) gsf_input_stream_new (section); zd = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW); cis = g_converter_input_stream_new (gis, (GConverter *) zd); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE); g_ptr_array_add (file->section_streams, cis); g_object_unref (zd); g_object_unref (gis); } else { GInputStream *stream = (GInputStream *) gsf_input_stream_new (section); g_ptr_array_add (file->section_streams, stream); } } /* for */ g_object_unref (input); input = NULL; } else { goto FAIL; } input = gsf_infile_child_by_name (ole, "\005HwpSummaryInformation"); if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1) { file->summary_info_stream = input; input = NULL; } else { goto FAIL; } input = gsf_infile_child_by_name (ole, "BinData"); if (input) { gint n_data = gsf_infile_num_children (GSF_INFILE (input)); for (gint i = 0; i < n_data; i++) { GsfInput *bin_data_input = gsf_infile_child_by_index (GSF_INFILE (input), i); if (gsf_infile_num_children (GSF_INFILE (bin_data_input)) != -1) { if (GSF_IS_INPUT (bin_data_input)) g_object_unref (bin_data_input); g_set_error_literal (error, HWP_FILE_ERROR, HWP_FILE_ERROR_INVALID, "invalid hwp file"); return; } if (file->is_compress) { GInputStream *gis; GZlibDecompressor *zd; GInputStream *cis; gis = (GInputStream *) gsf_input_stream_new (bin_data_input); zd = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW); cis = g_converter_input_stream_new (gis, (GConverter *) zd); g_filter_input_stream_set_close_base_stream (G_FILTER_INPUT_STREAM (cis), TRUE); g_ptr_array_add (file->bin_data_streams, cis); g_object_unref (zd); g_object_unref (gis); } else { GInputStream *stream = (GInputStream *) gsf_input_stream_new (bin_data_input); g_ptr_array_add (file->bin_data_streams, stream); } } g_object_unref (input); input = NULL; } input = gsf_infile_child_by_name (ole, "PrvText"); if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1) { file->prv_text_stream = input; input = NULL; } else { goto FAIL; } input = gsf_infile_child_by_name (ole, "PrvImage"); if (input && gsf_infile_num_children (GSF_INFILE (input)) == -1) { file->prv_image_stream = input; input = NULL; } else { goto FAIL; } return; FAIL: if (GSF_IS_INPUT (input)) g_object_unref (input); g_set_error_literal (error, HWP_FILE_ERROR, HWP_FILE_ERROR_INVALID, "invalid hwp file"); return; }
static bool _cjose_jwe_decrypt_dat_a256gcm( cjose_jwe_t *jwe, cjose_err *err) { EVP_CIPHER_CTX *ctx = NULL; // get A256GCM cipher const EVP_CIPHER *cipher = EVP_aes_256_gcm(); if (NULL == cipher) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } // instantiate and initialize a new openssl cipher context ctx = EVP_CIPHER_CTX_new(); if (NULL == ctx) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } EVP_CIPHER_CTX_init(ctx); // initialize context for decryption using A256GCM cipher and CEK and IV if (EVP_DecryptInit_ex(ctx, cipher, NULL, jwe->cek, jwe->part[2].raw) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } // set the expected GCM-mode authentication tag if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, jwe->part[4].raw_len, jwe->part[4].raw) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } // set GCM mode AAD data (hdr_b64u) by setting "out" to NULL int bytes_decrypted = 0; if (EVP_DecryptUpdate(ctx, NULL, &bytes_decrypted, (unsigned char *)jwe->part[0].b64u, jwe->part[0].b64u_len) != 1 || bytes_decrypted != jwe->part[0].b64u_len) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } // allocate buffer for the plaintext free(jwe->dat); jwe->dat_len = jwe->part[3].raw_len; if (!_cjose_jwe_malloc(jwe->dat_len, false, &jwe->dat, err)) { goto _cjose_jwe_decrypt_dat_a256gcm_fail; } // decrypt ciphertext to plaintext buffer if (EVP_DecryptUpdate(ctx, jwe->dat, &bytes_decrypted, jwe->part[3].raw, jwe->part[3].raw_len) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } jwe->dat_len = bytes_decrypted; // finalize the encryption if (EVP_DecryptFinal_ex(ctx, NULL, &bytes_decrypted) != 1) { CJOSE_ERROR(err, CJOSE_ERR_CRYPTO); goto _cjose_jwe_decrypt_dat_a256gcm_fail; } EVP_CIPHER_CTX_free(ctx); return true; _cjose_jwe_decrypt_dat_a256gcm_fail: if (NULL != ctx) { EVP_CIPHER_CTX_free(ctx); } return false; }
/* generate read/write keys for SSL v2 session */ int ssls2_generate_keys( DSSL_Session* sess, u_char* keyArg, uint32_t keyArgLen ) { DSSL_CipherSuite* suite = NULL; const EVP_CIPHER* c = NULL; const EVP_MD* digest = NULL; int rc = DSSL_RC_OK; uint32_t iv_len = 0; EVP_CIPHER_CTX* c_cipher = NULL; EVP_CIPHER_CTX* s_cipher = NULL; int keyLen = 0; u_char keydata[SSL2_MAX_KEYBLOCK_LEN]; if(keyArgLen > SSL2_KEYARG_MAX_LEN) { return NM_ERROR(DSSL_E_SSL_PROTOCOL_ERROR); } if( sess->c_dec.cipher_new != NULL ) { _ASSERT( FALSE ); EVP_CIPHER_CTX_cleanup( sess->c_dec.cipher_new ); free( sess->c_dec.cipher_new ); sess->c_dec.cipher_new = NULL; } if( sess->s_dec.cipher_new != NULL ) { _ASSERT( FALSE ); EVP_CIPHER_CTX_cleanup( sess->s_dec.cipher_new ); free( sess->s_dec.cipher_new ); sess->s_dec.cipher_new = NULL; } suite = DSSL_GetSSL2CipherSuite( sess->cipher_suite ); if( !suite ) return NM_ERROR( DSSL_E_SSL_CANNOT_DECRYPT ); c = EVP_get_cipherbyname( suite->enc ); if( c == NULL ) { _ASSERT( FALSE ); return NM_ERROR( DSSL_E_UNSPECIFIED_ERROR ); } digest = EVP_get_digestbyname( suite->digest ); iv_len = EVP_CIPHER_iv_length( c ); if( iv_len && iv_len != keyArgLen ) { return NM_ERROR( DSSL_E_SSL_PROTOCOL_ERROR ); } keyLen = c->key_len; _ASSERT( keyLen*2 <= sizeof(keydata) ); if( rc == DSSL_RC_OK ) { rc = ssl2_PRF( sess->master_secret, sess->master_key_len, sess->client_random, sess->client_challenge_len, sess->server_random, sess->server_connection_id_len, keydata, keyLen * 2 ); } /* create ciphers */ if( rc == DSSL_RC_OK ) { c_cipher = (EVP_CIPHER_CTX*) malloc( sizeof(EVP_CIPHER_CTX) ); s_cipher = (EVP_CIPHER_CTX*) malloc( sizeof(EVP_CIPHER_CTX) ); if( !c_cipher || !s_cipher ) { rc = NM_ERROR( DSSL_E_OUT_OF_MEMORY ); } EVP_CIPHER_CTX_init( c_cipher ); EVP_CIPHER_CTX_init( s_cipher ); } if( rc == DSSL_RC_OK ) { EVP_DecryptInit_ex( s_cipher, c, NULL, keydata, keyArg ); EVP_DecryptInit_ex( c_cipher, c, NULL, keydata + keyLen, keyArg ); sess->c_dec.cipher_new = c_cipher; c_cipher = NULL; sess->s_dec.cipher_new = s_cipher; s_cipher = NULL; sess->c_dec.md_new = digest; sess->s_dec.md_new = digest; } if( rc != DSSL_RC_OK ) { if( c_cipher ) { free( c_cipher ); c_cipher = NULL; } if( s_cipher ) { free( s_cipher ); s_cipher = NULL; } } /* store KEY-ARG data for session cache */ if( rc == DSSL_RC_OK) { memset(sess->ssl2_key_arg, 0, SSL2_KEYARG_MAX_LEN); memcpy(sess->ssl2_key_arg, keyArg, keyArgLen); sess->ssl2_key_arg_len = keyArgLen; } return rc; }