Example #1
0
OSStatus    AES_GCM_Decrypt( AES_GCM_Context *inContext, const void *inSrc, size_t inLen, void *inDst )
{
    OSStatus        err;
    
    err = gcm_decrypt( inDst, inSrc, inLen, &inContext->ctx );
    require_noerr( err, exit );
    
exit:
    return( err );
}
Example #2
0
    void Document::decrypt(const uint8_t* key,
            int key_size,
            const std::string& key_name)
    {
        // Only accept 256bit keys.
        if (k_key_size != key_size)
        {
            throw LJ__Exception("Decrypt key must be 256bits.");
        }

        // Get the document to decrypt.
        const lj::bson::Node& source_node =
                doc_->nav(k_crypt_data).nav(key_name);
        lj::bson::Binary_type bt;
        uint32_t source_size;
        const uint8_t* source = lj::bson::as_binary(source_node,
                &bt,
                &source_size);

        // Get the initialization vector for the encrypted data.
        const lj::bson::Node& ivector_node =
                doc_->nav(k_crypt_vector).nav(key_name);
        uint32_t iv_size;
        const uint8_t* iv = lj::bson::as_binary(ivector_node,
                &bt,
                &iv_size);

        // Check to make sure the initialization vector is the correct length.
        if (GCM_IV_SIZE != iv_size)
        {
            throw LJ__Exception("Initialization vector for this encrypted data is incorrect.");
        }

        // Prepare all the data structures for the AES crypto in GCM mode.
        struct aes_ctx cipher_ctx;
        aes_set_encrypt_key(&cipher_ctx, key_size, key);
        struct gcm_key auth_key;
        gcm_set_key(&auth_key, &cipher_ctx, (nettle_crypt_func*) & aes_encrypt);
        struct gcm_ctx auth_ctx;
        gcm_set_iv(&auth_ctx, &auth_key, GCM_IV_SIZE, iv);

        // Perform the actual encryption.
        std::unique_ptr < uint8_t[] > destination(new uint8_t[source_size]);
        gcm_decrypt(&auth_ctx,
                &auth_key,
                &cipher_ctx,
                (nettle_crypt_func*) & aes_encrypt,
                source_size,
                destination.get(),
                source);

        // Extract the authentication information.
        uint8_t auth_tag[GCM_BLOCK_SIZE];
        gcm_digest(&auth_ctx, &auth_key, &cipher_ctx, (nettle_crypt_func*) & aes_encrypt, GCM_BLOCK_SIZE, auth_tag);

        // Get the  authentication vector from the encryption.
        const lj::bson::Node& authentication_node =
                doc_->nav(k_crypt_auth).nav(key_name);
        uint32_t authentication_size;
        const uint8_t* original_auth_tag = lj::bson::as_binary(authentication_node,
                &bt,
                &authentication_size);

        // Check to make sure the authentication tag is the correct size.
        if (GCM_BLOCK_SIZE != authentication_size)
        {
            throw LJ__Exception("Authentication tag for this encrypted data is incorrect.");
        }

        // Compare the authentication tag from decryption to the authentication tag from encryption.
        if (memcmp(auth_tag, original_auth_tag, GCM_BLOCK_SIZE) != 0)
        {
            throw LJ__Exception("Authentication tags did not match. Data may be corrupted.");
        }

        // The destination should now contain whatever was originally encrypted.
        // Turn the data back into a bson document
        lj::bson::Node changes(lj::bson::Type::k_document,
                destination.get());

        // Clean up anything sensitive from memory.
        lj::Wiper < uint8_t[]>::wipe(destination, source_size);
        lj::Wiper < uint8_t[]>::wipe(auth_tag, GCM_BLOCK_SIZE);

        // try to combine the documents.  This may throw an exception if things are
        // messed up.
        lj::bson::combine(doc_->nav("."), changes.nav("."));

        // Remove the encrypted data from the document.
        doc_->nav(k_crypt_vector).set_child(key_name, nullptr);
        doc_->nav(k_crypt_auth).set_child(key_name, nullptr);
        doc_->nav(k_crypt_data).set_child(key_name, nullptr);
    }