Commit 43fdd617 authored by Paul Bakker's avatar Paul Bakker
Browse files

Merged update certificate verification for EC certificates into

development
parents ca2da515 fff80f88
......@@ -31,6 +31,8 @@
/**
* \brief ECDSA context structure
*
* \note Purposefully begins with the same members as struct ecp_keypair.
*/
typedef struct
{
......@@ -140,6 +142,16 @@ int ecdsa_read_signature( ecdsa_context *ctx,
int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid,
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng );
/**
* \brief Set an ECDSA context from an EC key pair
*
* \param ctx ECDSA context to set
* \param key EC key to use
*
* \return 0 on success, or a POLARSSL_ERR_ECP code.
*/
int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key );
/**
* \brief Initialize context
*
......
......@@ -95,6 +95,8 @@ ecp_group;
* \brief ECP key pair structure
*
* A generic key pair that could be used for ECDSA, fixed ECDH, etc.
*
* \note Members purposefully in the same order as struc ecdsa_context.
*/
typedef struct
{
......
......@@ -77,14 +77,14 @@
* PEM 1 9
* PKCS#12 1 4 (Started from top)
* X509 2 25
* PK 2 1 (Started from top)
* PK 2 3 (Started from top)
* DHM 3 6
* PKCS5 3 4 (Started from top)
* RSA 4 9
* ECP 4 4 (Started from top)
* MD 5 4
* CIPHER 6 5
* SSL 6 5 (Started from top)
* SSL 6 6 (Started from top)
* SSL 7 31
*
* Module dependent error code (5 bits 0x.08.-0x.F8.)
......
......@@ -24,17 +24,29 @@
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_PK_H
#define POLARSSL_PK_H
#include "config.h"
#include "md.h"
#if defined(POLARSSL_RSA_C)
#include "rsa.h"
#endif
#if defined(POLARSSL_ECP_C)
#include "ecp.h"
#endif
#if defined(POLARSSL_ECDSA_C)
#include "ecdsa.h"
#endif
#define POLARSSL_ERR_PK_MALLOC_FAILED -0x2F80 /**< Memory alloation failed. */
#define POLARSSL_ERR_PK_TYPE_MISMATCH -0x2F00 /**< Type mismatch, eg attempt to use a RSA key as EC, or to modify key type */
#define POLARSSL_ERR_PK_TYPE_MISMATCH -0x2F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */
#define POLARSSL_ERR_PK_BAD_INPUT_DATA -0x2E80 /**< Bad input parameters to function. */
#if defined(POLARSSL_RSA_C)
/**
......@@ -43,7 +55,7 @@
* \warning You must make sure the PK context actually holds an RSA context
* before using this macro!
*/
#define pk_rsa( pk ) ( (rsa_context *) (pk).data )
#define pk_rsa( pk ) ( (rsa_context *) (pk).pk_ctx )
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECP_C)
......@@ -53,7 +65,7 @@
* \warning You must make sure the PK context actually holds an EC context
* before using this macro!
*/
#define pk_ec( pk ) ( (ecp_keypair *) (pk).data )
#define pk_ec( pk ) ( (ecp_keypair *) (pk).pk_ctx )
#endif /* POLARSSL_ECP_C */
......@@ -72,58 +84,161 @@ typedef enum {
POLARSSL_PK_ECDSA,
} pk_type_t;
/**
* \brief Types for interfacing with the debug module
*/
typedef enum
{
POLARSSL_PK_DEBUG_NONE = 0,
POLARSSL_PK_DEBUG_MPI,
POLARSSL_PK_DEBUG_ECP,
} pk_debug_type;
/**
* \brief Item to send to the debug module
*/
typedef struct
{
pk_debug_type type;
char *name;
void *value;
} pk_debug_item;
/** Maximum number of item send for debugging, plus 1 */
#define POLARSSL_PK_DEBUG_MAX_ITEMS 3
/**
* \brief Public key information and operations
*/
typedef struct
{
/** Public key type */
pk_type_t type;
/** Type name */
const char *name;
/** Get key size in bits */
size_t (*get_size)( const void * );
/** Tell if the context implements this type (eg ECKEY can do ECDSA) */
int (*can_do)( pk_type_t type );
/** Verify signature */
int (*verify_func)( void *ctx, md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len );
/** Allocate a new context */
void * (*ctx_alloc_func)( void );
/** Free the given context */
void (*ctx_free_func)( void *ctx );
/** Interface with the debug module */
void (*debug_func)( const void *ctx, pk_debug_item *items );
} pk_info_t;
/**
* \brief Public key container
*/
typedef struct
{
pk_type_t type; /**< Public key type */
void * data; /**< Public key data */
int dont_free; /**< True if data must not be freed */
const pk_info_t * pk_info; /**< Public key informations */
void * pk_ctx; /**< Underlying public key context */
} pk_context;
/**
* \brief Return information associated with the given PK type
*
* \param type PK type to search for.
*
* \return The PK info associated with the type or NULL if not found.
*/
const pk_info_t *pk_info_from_type( pk_type_t pk_type );
/**
* \brief Initialize a pk_context (as NONE)
*/
void pk_init( pk_context *ctx );
/**
* \brief Initialize a PK context with the information given
* and allocates the type-specific PK subcontext.
*
* \param ctx Context to initialize. Must be empty (type NONE).
* \param info Information to use
*
* \return 0 on success,
* POLARSSL_ERR_PK_BAD_INPUT_DATA on invalid input,
* POLARSSL_ERR_PK_MALLOC_FAILED on allocation failure.
*/
int pk_init_ctx( pk_context *ctx, const pk_info_t *info );
/**
* \brief Free a pk_context
*/
void pk_free( pk_context *ctx );
/**
* \brief Set a pk_context to a given type
* \brief Get the size in bits of the underlying key
*
* \param ctx Context to initialize
* \param type Type of key
* \param ctx Context to use
*
* \note Once the type of a key has been set, it cannot be reset.
* If you want to do so, you need to use pk_free() first.
* \return Key size in bits, or 0 on error
*/
size_t pk_get_size( const pk_context *ctx );
/**
* \brief Tell if a context can do the operation given by type
*
* \param ctx Context to test
* \param type Target type
*
* \return O on success,
* POLARSSL_ERR_PK_MALLOC_FAILED on memory allocation fail,
* POLARSSL_ERR_PK_TYPE_MISMATCH on attempts to reset type.
* \return 0 if context can't do the operations,
* 1 otherwise.
*/
int pk_set_type( pk_context *ctx, pk_type_t type );
int pk_can_do( pk_context *ctx, pk_type_t type );
#if defined(POLARSSL_RSA_C)
/**
* \brief Wrap a RSA context in a PK context
* \brief Verify signature
*
* \param ctx PK context to use
* \param md_alg Hash algorithm used
* \param hash Hash of the message to sign
* \param hash_len Hash length
* \param sig Signature to verify
* \param sig_len Signature length
*
* \param ctx PK context to initiliaze
* \param rsa RSA context to use
* \return 0 on success (signature is valid),
* or a specific error code.
*/
int pk_verify( pk_context *ctx, md_type_t md_alg,
const unsigned char *hash, size_t hash_len,
const unsigned char *sig, size_t sig_len );
/**
* \brief Export debug information
*
* \note The PK context must be freshly initialized.
* \param ctx Context to use
* \param items Place to write debug items
*
* \return O on success,
* POLARSSL_ERR_PK_TYPE_MISMATCH if ctx was not empty.
* \return 0 on sucess or POLARSSL_ERR_PK_BAD_INPUT_DATA
*/
int pk_wrap_rsa( pk_context *ctx, const rsa_context *rsa);
#endif /* POLARSSL_RSA_C */
int pk_debug( const pk_context *ctx, pk_debug_item *items );
/**
* \brief Access the type name
*
* \param ctx Context to use
*
* \return Type name on success, or "invalid PK"
*/
const char * pk_get_name( const pk_context *ctx );
#ifdef __cplusplus
}
#endif
#endif /* pk.h */
#endif /* POLARSSL_PK_H */
/**
* \file pk.h
*
* \brief Public Key abstraction layer: wrapper functions
*
* Copyright (C) 2006-2013, Brainspark B.V.
*
* This file is part of PolarSSL (http://www.polarssl.org)
* Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef POLARSSL_PK_WRAP_H
#define POLARSSL_PK_WRAP_H
#include "config.h"
#include "pk.h"
#if defined(POLARSSL_RSA_C)
extern const pk_info_t rsa_info;
#endif
#if defined(POLARSSL_ECP_C)
extern const pk_info_t eckey_info;
extern const pk_info_t eckeydh_info;
#endif
#if defined(POLARSSL_ECDSA_C)
extern const pk_info_t ecdsa_info;
#endif
#endif /* POLARSSL_PK_WRAP_H */
......@@ -451,7 +451,7 @@ int rsa_pkcs1_verify( rsa_context *ctx,
md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
const unsigned char *sig );
/**
* \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY)
......@@ -474,7 +474,7 @@ int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx,
md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
const unsigned char *sig );
/**
* \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY)
......@@ -504,7 +504,18 @@ int rsa_rsassa_pss_verify( rsa_context *ctx,
md_type_t md_alg,
unsigned int hashlen,
const unsigned char *hash,
unsigned char *sig );
const unsigned char *sig );
/**
* \brief Copy the components of an RSA context
*
* \param dst Destination context
* \param src Source context
*
* \return O on success,
* POLARSSL_ERR_MPI_MALLOC_FAILED on memory allocation failure
*/
int rsa_copy( rsa_context *dst, const rsa_context *src );
/**
* \brief Free the components of an RSA key
......
......@@ -110,7 +110,7 @@
#define POLARSSL_ERR_SSL_BAD_HS_PROTOCOL_VERSION -0x6E80 /**< Handshake protocol not within min/max boundaries */
#define POLARSSL_ERR_SSL_BAD_HS_NEW_SESSION_TICKET -0x6E00 /**< Processing of the NewSessionTicket handshake message failed. */
#define POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED -0x6D80 /**< Session ticket has expired. */
#define POLARSSL_ERR_SSL_PK_TYPE_MISMATCH -0x6D00 /**< Public key type mismatch (eg, asked for RSA key exchange and presented EC key) */
/*
* Various constants
......
......@@ -40,6 +40,7 @@ set(src
pkcs11.c
pkcs12.c
pk.c
pk_wrap.c
rsa.c
sha1.c
sha256.c
......
......@@ -49,7 +49,7 @@ OBJS= aes.o arc4.o asn1parse.o \
oid.o \
padlock.o pbkdf2.o pem.o \
pkcs5.o pkcs11.o pkcs12.o \
pk.o \
pk.o pk_wrap.o \
rsa.o sha1.o sha256.o \
sha512.o ssl_cache.o ssl_cli.o \
ssl_srv.o ssl_ciphersuites.o \
......
......@@ -130,6 +130,12 @@ int mpi_copy( mpi *X, const mpi *Y )
if( X == Y )
return( 0 );
if( Y->p == NULL )
{
mpi_free( X );
return( 0 );
}
for( i = Y->n - 1; i > 0; i-- )
if( Y->p[i] != 0 )
break;
......
......@@ -225,6 +225,39 @@ void debug_print_mpi( const ssl_context *ssl, int level,
#endif /* POLARSSL_BIGNUM_C */
#if defined(POLARSSL_X509_PARSE_C)
static void debug_print_pk( const ssl_context *ssl, int level,
const char *file, int line,
const char *text, const pk_context *pk )
{
size_t i;
pk_debug_item items[POLARSSL_PK_DEBUG_MAX_ITEMS];
char name[16];
memset( items, 0, sizeof( items ) );
if( pk_debug( pk, items ) != 0 )
{
debug_print_msg( ssl, level, file, line, "invalid PK context" );
return;
}
for( i = 0; i < sizeof( items ); i++ )
{
if( items[i].type == POLARSSL_PK_DEBUG_NONE )
return;
snprintf( name, sizeof( name ), "%s%s", text, items[i].name );
name[sizeof( name ) - 1] = '\0';
if( items[i].type == POLARSSL_PK_DEBUG_MPI )
debug_print_mpi( ssl, level, file, line, name, items[i].value );
else if( items[i].type == POLARSSL_PK_DEBUG_ECP )
debug_print_ecp( ssl, level, file, line, name, items[i].value );
else
debug_print_msg( ssl, level, file, line, "should not happen" );
}
}
void debug_print_crt( const ssl_context *ssl, int level,
const char *file, int line,
const char *text, const x509_cert *crt )
......@@ -250,25 +283,7 @@ void debug_print_crt( const ssl_context *ssl, int level,
str[maxlen] = '\0';
ssl->f_dbg( ssl->p_dbg, level, str );
#if defined(POLARSSL_RSA_C)
if( crt->pk.type == POLARSSL_PK_RSA )
{
debug_print_mpi( ssl, level, file, line,
"crt->rsa.N", &pk_rsa( crt->pk )->N );
debug_print_mpi( ssl, level, file, line,
"crt->rsa.E", &pk_rsa( crt->pk )->E );
} else
#endif /* POLARSSL_RSA_C */
#if defined(POLARSSL_ECP_C)
if( crt->pk.type == POLARSSL_PK_ECKEY ||
crt->pk.type == POLARSSL_PK_ECKEY_DH )
{
debug_print_ecp( ssl, level, file, line,
"crt->eckey.Q", &pk_ec( crt->pk )->Q );
} else
#endif /* POLARSSL_ECP_C */
debug_print_msg( ssl, level, file, line,
"crt->pk.type is not valid" );
debug_print_pk( ssl, level, file, line, "crt->", &crt->pk );
crt = crt->next;
}
......
......@@ -283,6 +283,20 @@ int ecdsa_genkey( ecdsa_context *ctx, ecp_group_id gid,
ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
}
/*
* Set context from an ecp_keypair
*/
int ecdsa_from_keypair( ecdsa_context *ctx, const ecp_keypair *key )
{
int ret = ecp_group_copy( &ctx->grp, &key->grp ) ||
mpi_copy( &ctx->d, &key->d ) ||
ecp_copy( &ctx->Q, &key->Q );
if( ret != 0 )
ecdsa_free( ctx );
return( ret );
}
/*
* Initialize context
......
......@@ -252,6 +252,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
snprintf( buf, buflen, "PK - Memory alloation failed" );
if( use_ret == -(POLARSSL_ERR_PK_TYPE_MISMATCH) )
snprintf( buf, buflen, "PK - Type mismatch, eg attempt to use a RSA key as EC, or to modify key type" );
if( use_ret == -(POLARSSL_ERR_PK_BAD_INPUT_DATA) )
snprintf( buf, buflen, "PK - Bad input parameters to function" );
#endif /* POLARSSL_PK_C */
#if defined(POLARSSL_PKCS12_C)
......@@ -373,6 +375,8 @@ void polarssl_strerror( int ret, char *buf, size_t buflen )
snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" );
if( use_ret == -(POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED) )
snprintf( buf, buflen, "SSL - Session ticket has expired" );
if( use_ret == -(POLARSSL_ERR_SSL_PK_TYPE_MISMATCH) )
snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" );
#endif /* POLARSSL_SSL_TLS_C */
#if defined(POLARSSL_X509_PARSE_C)
......
......@@ -26,6 +26,7 @@
#include "polarssl/config.h"
#include "polarssl/pk.h"
#include "polarssl/pk_wrap.h"
#if defined(POLARSSL_RSA_C)
#include "polarssl/rsa.h"
......@@ -37,15 +38,6 @@
#include "polarssl/ecdsa.h"
#endif
#if defined(POLARSSL_MEMORY_C)
#include "polarssl/memory.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#include <stdlib.h>
/*
* Initialise a pk_context
*/
......@@ -54,9 +46,8 @@ void pk_init( pk_context *ctx )
if( ctx == NULL )
return;
ctx->type = POLARSSL_PK_NONE;
ctx->data = NULL;
ctx->dont_free = 0;
ctx->pk_info = NULL;
ctx->pk_ctx = NULL;
}
/*
......@@ -64,87 +55,116 @@ void pk_init( pk_context *ctx )
*/
void pk_free( pk_context *ctx )
{
if( ctx == NULL )
if( ctx == NULL || ctx->pk_info == NULL)
return;
ctx->pk_info->ctx_free_func( ctx->pk_ctx );
ctx->pk_ctx = NULL;
ctx->pk_info = NULL;
}
/*
* Get pk_info structure from type
*/
const pk_info_t * pk_info_from_type( pk_type_t pk_type )
{
switch( pk_type ) {
#if defined(POLARSSL_RSA_C)
if( ctx->type == POLARSSL_PK_RSA )
rsa_free( ctx->data );
else
case POLARSSL_PK_RSA:
return &rsa_info;
#endif
#if defined(POLARSSL_ECP_C)
if( ctx->type == POLARSSL_PK_ECKEY || ctx->type == POLARSSL_PK_ECKEY_DH )
ecp_keypair_free( ctx->data );
else
case POLARSSL_PK_ECKEY:
return &eckey_info;
case POLARSSL_PK_ECKEY_DH:
return &eckeydh_info;
#endif
#if defined(POLARSSL_ECDSA_C)
if( ctx->type == POLARSSL_PK_ECDSA )
ecdsa_free( ctx->data );
else
case POLARSSL_PK_ECDSA:
return &ecdsa_info;
#endif
{
; /* guard for the else's above */
default:
return NULL;
}
}
/*
* Initialise context
*/
int pk_init_ctx( pk_context *ctx, const pk_info_t *info )
{
if( ctx == NULL || info == NULL || ctx->pk_info != NULL )
return( POLARSSL_ERR_PK_BAD_INPUT_DATA );