/*
* Copyright (C) 2011-2012 Free Software Foundation, Inc.
*
* Author: Nikos Mavrogiannopoulos
*
* This file is part of GnuTLS.
*
* The GnuTLS is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see
*
*/
#include "gnutls_int.h"
#include
#include "errors.h"
#include
#include
/* Supported ECC curves
*/
static const gnutls_ecc_curve_entry_st ecc_curves[] = {
{
.name = "SECP192R1",
.oid = "1.2.840.10045.3.1.1",
.id = GNUTLS_ECC_CURVE_SECP192R1,
.tls_id = 19,
.pk = GNUTLS_PK_ECDSA,
.size = 24,
},
{
.name = "SECP224R1",
.oid = "1.3.132.0.33",
.id = GNUTLS_ECC_CURVE_SECP224R1,
.tls_id = 21,
.pk = GNUTLS_PK_ECDSA,
.size = 28,
},
{
.name = "SECP256R1",
.oid = "1.2.840.10045.3.1.7",
.id = GNUTLS_ECC_CURVE_SECP256R1,
.tls_id = 23,
.pk = GNUTLS_PK_ECDSA,
.size = 32,
},
{
.name = "SECP384R1",
.oid = "1.3.132.0.34",
.id = GNUTLS_ECC_CURVE_SECP384R1,
.tls_id = 24,
.pk = GNUTLS_PK_ECDSA,
.size = 48,
},
{
.name = "SECP521R1",
.oid = "1.3.132.0.35",
.id = GNUTLS_ECC_CURVE_SECP521R1,
.tls_id = 25,
.pk = GNUTLS_PK_ECDSA,
.size = 66,
},
{
.name = "X25519",
.id = GNUTLS_ECC_CURVE_X25519,
.tls_id = 29,
.pk = GNUTLS_PK_ECDHX,
.size = 32,
},
{0, 0, 0}
};
#define GNUTLS_ECC_CURVE_LOOP(b) \
{ const gnutls_ecc_curve_entry_st *p; \
for(p = ecc_curves; p->name != NULL; p++) { b ; } }
/* Returns the TLS id of the given curve
*/
int _gnutls_tls_id_to_ecc_curve(int num)
{
gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
GNUTLS_ECC_CURVE_LOOP(
if (p->tls_id == num && _gnutls_pk_curve_exists(p->id)) {
ret = p->id;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_list:
*
* Get the list of supported elliptic curves.
*
* This function is not thread safe.
*
* Returns: Return a (0)-terminated list of #gnutls_ecc_curve_t
* integers indicating the available curves.
**/
const gnutls_ecc_curve_t *gnutls_ecc_curve_list(void)
{
static gnutls_ecc_curve_t supported_curves[MAX_ALGOS] = { 0 };
if (supported_curves[0] == 0) {
int i = 0;
GNUTLS_ECC_CURVE_LOOP(
if (_gnutls_pk_curve_exists(p->id))
supported_curves[i++] = p->id;
);
supported_curves[i++] = 0;
}
return supported_curves;
}
/* Maps numbers to TLS NamedCurve IDs (RFC4492).
* Returns a negative number on error.
*/
int _gnutls_ecc_curve_get_tls_id(gnutls_ecc_curve_t supported_ecc)
{
int ret = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == supported_ecc) {
ret = p->tls_id;
break;
}
);
return ret;
}
/**
* gnutls_oid_to_ecc_curve:
* @oid: is a curve's OID
*
* Returns: return a #gnutls_ecc_curve_t value corresponding to
* the specified OID, or %GNUTLS_ECC_CURVE_INVALID on error.
*
* Since: 3.4.3
**/
gnutls_ecc_curve_t gnutls_oid_to_ecc_curve(const char *oid)
{
gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
GNUTLS_ECC_CURVE_LOOP(
if (p->oid && strcasecmp(p->oid, oid) == 0 && _gnutls_pk_curve_exists(p->id)) {
ret = p->id;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_get_id:
* @name: is a curve name
*
* The names are compared in a case insensitive way.
*
* Returns: return a #gnutls_ecc_curve_t value corresponding to
* the specified curve, or %GNUTLS_ECC_CURVE_INVALID on error.
*
* Since: 3.4.3
**/
gnutls_ecc_curve_t gnutls_ecc_curve_get_id(const char *name)
{
gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_INVALID;
GNUTLS_ECC_CURVE_LOOP(
if (strcasecmp(p->name, name) == 0 && _gnutls_pk_curve_exists(p->id)) {
ret = p->id;
break;
}
);
return ret;
}
/*-
* _gnutls_ecc_bits_to_curve:
* @bits: is a security parameter in bits
*
* Returns: return a #gnutls_ecc_curve_t value corresponding to
* the specified bit length, or %GNUTLS_ECC_CURVE_INVALID on error.
-*/
gnutls_ecc_curve_t _gnutls_ecc_bits_to_curve(int bits)
{
gnutls_ecc_curve_t ret = GNUTLS_ECC_CURVE_SECP256R1;
GNUTLS_ECC_CURVE_LOOP(
if (8 * p->size >= bits && _gnutls_pk_curve_exists(p->id)) {
ret = p->id;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_get_name:
* @curve: is an ECC curve
*
* Convert a #gnutls_ecc_curve_t value to a string.
*
* Returns: a string that contains the name of the specified
* curve or %NULL.
*
* Since: 3.0
**/
const char *gnutls_ecc_curve_get_name(gnutls_ecc_curve_t curve)
{
const char *ret = NULL;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == curve) {
ret = p->name;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_get_oid:
* @curve: is an ECC curve
*
* Convert a #gnutls_ecc_curve_t value to its object identifier.
*
* Returns: a string that contains the OID of the specified
* curve or %NULL.
*
* Since: 3.4.3
**/
const char *gnutls_ecc_curve_get_oid(gnutls_ecc_curve_t curve)
{
const char *ret = NULL;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == curve) {
ret = p->oid;
break;
}
);
return ret;
}
/*-
* _gnutls_ecc_curve_get_params:
* @curve: is an ECC curve
*
* Returns the information on a curve.
*
* Returns: a pointer to #gnutls_ecc_curve_entry_st or %NULL.
-*/
const gnutls_ecc_curve_entry_st
*_gnutls_ecc_curve_get_params(gnutls_ecc_curve_t curve)
{
const gnutls_ecc_curve_entry_st *ret = NULL;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == curve) {
ret = p;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_get_size:
* @curve: is an ECC curve
*
* Returns: the size in bytes of the curve or 0 on failure.
*
* Since: 3.0
**/
int gnutls_ecc_curve_get_size(gnutls_ecc_curve_t curve)
{
int ret = 0;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == curve) {
ret = p->size;
break;
}
);
return ret;
}
/**
* gnutls_ecc_curve_get_pk:
* @curve: is an ECC curve
*
* Returns: the public key algorithm associated with the named curve or %GNUTLS_PK_UNKNOWN.
*
* Since: 3.5.0
**/
gnutls_pk_algorithm_t gnutls_ecc_curve_get_pk(gnutls_ecc_curve_t curve)
{
int ret = GNUTLS_PK_UNKNOWN;
GNUTLS_ECC_CURVE_LOOP(
if (p->id == curve) {
ret = p->pk;
break;
}
);
return ret;
}