115 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			115 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 2015-2016 Virgil Security Inc.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Lead Maintainer: Virgil Security Inc. <support@virgilsecurity.com>
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * All rights reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Redistribution and use in source and binary forms, with or without
							 | 
						||
| 
								 | 
							
								 * modification, are permitted provided that the following conditions are
							 | 
						||
| 
								 | 
							
								 * met:
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *     (1) Redistributions of source code must retain the above copyright
							 | 
						||
| 
								 | 
							
								 *     notice, this list of conditions and the following disclaimer.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *     (2) Redistributions in binary form must reproduce the above copyright
							 | 
						||
| 
								 | 
							
								 *     notice, this list of conditions and the following disclaimer in
							 | 
						||
| 
								 | 
							
								 *     the documentation and/or other materials provided with the
							 | 
						||
| 
								 | 
							
								 *     distribution.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *     (3) Neither the name of the copyright holder nor the names of its
							 | 
						||
| 
								 | 
							
								 *     contributors may be used to endorse or promote products derived from
							 | 
						||
| 
								 | 
							
								 *     this software without specific prior written permission.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR
							 | 
						||
| 
								 | 
							
								 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
							 | 
						||
| 
								 | 
							
								 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
							 | 
						||
| 
								 | 
							
								 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
							 | 
						||
| 
								 | 
							
								 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
							 | 
						||
| 
								 | 
							
								 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
							 | 
						||
| 
								 | 
							
								 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
							 | 
						||
| 
								 | 
							
								 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
							 | 
						||
| 
								 | 
							
								 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
							 | 
						||
| 
								 | 
							
								 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
							 | 
						||
| 
								 | 
							
								 * POSSIBILITY OF SUCH DAMAGE.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This file is part of extension to mbed TLS (https://tls.mbed.org)
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if !defined(MBEDTLS_CONFIG_FILE)
							 | 
						||
| 
								 | 
							
								#include "mbedtls/config.h"
							 | 
						||
| 
								 | 
							
								#else
							 | 
						||
| 
								 | 
							
								#include MBEDTLS_CONFIG_FILE
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if defined(MBEDTLS_KDF2_C)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "mbedtls/kdf2.h"
							 | 
						||
| 
								 | 
							
								#include "mbedtls/md.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <math.h>
							 | 
						||
| 
								 | 
							
								#include <string.h>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KDF2_TRY(invocation) \
							 | 
						||
| 
								 | 
							
								do { \
							 | 
						||
| 
								 | 
							
								    result = invocation; \
							 | 
						||
| 
								 | 
							
								    if((result) < 0) { \
							 | 
						||
| 
								 | 
							
								        goto exit; \
							 | 
						||
| 
								 | 
							
								    } \
							 | 
						||
| 
								 | 
							
								} while (0)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define KDF2_CEIL(x,y) (1 + ((x - 1) / y))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int mbedtls_kdf2(const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen,
							 | 
						||
| 
								 | 
							
								        unsigned char * output, size_t olen)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								    int result = 0;
							 | 
						||
| 
								 | 
							
								    size_t counter = 1;
							 | 
						||
| 
								 | 
							
								    size_t counter_len = 0;
							 | 
						||
| 
								 | 
							
								    unsigned char counter_string[4] = {0x0};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    unsigned char hash[MBEDTLS_MD_MAX_SIZE] = {0x0};
							 | 
						||
| 
								 | 
							
								    unsigned char hash_len = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    size_t olen_actual = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    mbedtls_md_context_t md_ctx;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (md_info == NULL)
							 | 
						||
| 
								 | 
							
								        return( MBEDTLS_ERR_KDF2_BAD_INPUT_DATA );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Initialize digest context
							 | 
						||
| 
								 | 
							
								    mbedtls_md_init(&md_ctx);
							 | 
						||
| 
								 | 
							
								    KDF2_TRY(mbedtls_md_setup(&md_ctx, md_info, 0));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Get hash parameters
							 | 
						||
| 
								 | 
							
								    hash_len = mbedtls_md_get_size(md_info);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Get KDF parameters
							 | 
						||
| 
								 | 
							
								    counter_len = KDF2_CEIL(olen, hash_len);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Start hashing
							 | 
						||
| 
								 | 
							
								    for(; counter <= counter_len; ++counter) {
							 | 
						||
| 
								 | 
							
								        counter_string[0] = (unsigned char)((counter >> 24) & 255);
							 | 
						||
| 
								 | 
							
								        counter_string[1] = (unsigned char)((counter >> 16) & 255);
							 | 
						||
| 
								 | 
							
								        counter_string[2] = (unsigned char)((counter >> 8)) & 255;
							 | 
						||
| 
								 | 
							
								        counter_string[3] = (unsigned char)(counter & 255);
							 | 
						||
| 
								 | 
							
								        KDF2_TRY(mbedtls_md_starts(&md_ctx));
							 | 
						||
| 
								 | 
							
								        KDF2_TRY(mbedtls_md_update(&md_ctx, input, ilen));
							 | 
						||
| 
								 | 
							
								        KDF2_TRY(mbedtls_md_update(&md_ctx, counter_string, 4));
							 | 
						||
| 
								 | 
							
								        if (olen_actual + hash_len <= olen) {
							 | 
						||
| 
								 | 
							
								            KDF2_TRY(mbedtls_md_finish(&md_ctx, output + olen_actual));
							 | 
						||
| 
								 | 
							
								            olen_actual += hash_len;
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            KDF2_TRY(mbedtls_md_finish(&md_ctx, hash));
							 | 
						||
| 
								 | 
							
								            memcpy(output + olen_actual, hash, olen - olen_actual);
							 | 
						||
| 
								 | 
							
								            olen_actual = olen;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								exit:
							 | 
						||
| 
								 | 
							
								    mbedtls_md_free(&md_ctx);
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif /* MBEDTLS_KDF2_C */
							 |