Exemple #1
0
/**
 * @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;

}
Exemple #2
0
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;

}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
/* 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);
}
Exemple #6
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);
}
Exemple #7
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;
}
Exemple #8
0
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;
    
}
Exemple #10
0
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");
}
Exemple #11
0
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;
}
Exemple #12
0
    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;
    }
Exemple #13
0
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);
	}
Exemple #14
0
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;
}
Exemple #15
0
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");
    }
Exemple #16
0
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;
}
Exemple #17
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;
}
Exemple #19
0
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;
}
Exemple #20
0
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);
}
Exemple #21
0
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);
}
Exemple #22
0
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;
}
Exemple #23
0
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;
	}
Exemple #24
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;
}
Exemple #26
0
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;
}
Exemple #27
0
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;
}
Exemple #28
0
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;
}
Exemple #29
0
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;
}
Exemple #30
0
/* 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;
}