File: [local] / src / sbin / isakmpd / Attic / math_group.c (download)
Revision 1.32, Mon Jul 24 11:45:44 2006 UTC (17 years, 10 months ago) by ho
Branch: MAIN
CVS Tags: OPENBSD_4_7_BASE, OPENBSD_4_7, OPENBSD_4_6_BASE, OPENBSD_4_6, OPENBSD_4_5_BASE, OPENBSD_4_5, OPENBSD_4_4_BASE, OPENBSD_4_4, OPENBSD_4_3_BASE, OPENBSD_4_3, OPENBSD_4_2_BASE, OPENBSD_4_2, OPENBSD_4_1_BASE, OPENBSD_4_1, OPENBSD_4_0_BASE, OPENBSD_4_0 Changes since 1.31: +8 -8 lines
Style; return is not a function. hshoexer@ ok.
|
/* $OpenBSD: math_group.c,v 1.32 2006/07/24 11:45:44 ho Exp $ */
/* $EOM: math_group.c,v 1.25 2000/04/07 19:53:26 niklas Exp $ */
/*
* Copyright (c) 1998 Niels Provos. All rights reserved.
* Copyright (c) 1999, 2000 Niklas Hallqvist. 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.
*
* 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 code was written under funding by Ericsson Radio Systems.
*/
#include <sys/param.h>
#include <stdlib.h>
#include <string.h>
#include "log.h"
#include "math_2n.h"
#include "math_ec2n.h"
#include "math_group.h"
#include "math_mp.h"
#include "util.h"
/* We do not want to export these definitions. */
int modp_getlen(struct group *);
void modp_getraw(struct group *, math_mp_t, u_int8_t *);
int modp_setraw(struct group *, math_mp_t, u_int8_t *, int);
int modp_setrandom(struct group *, math_mp_t);
int modp_operation(struct group *, math_mp_t, math_mp_t, math_mp_t);
int modp_validate_public(struct group *, math_mp_t);
int ec2n_getlen(struct group *);
void ec2n_getraw(struct group *, ec2np_ptr, u_int8_t *);
int ec2n_setraw(struct group *, ec2np_ptr, u_int8_t *, int);
int ec2n_setrandom(struct group *, ec2np_ptr);
int ec2n_operation(struct group *, ec2np_ptr, ec2np_ptr, ec2np_ptr);
int ec2n_validate_public(struct group *, ec2np_ptr);
struct ec2n_group {
ec2np_t gen; /* Generator */
ec2ng_t grp;
ec2np_t a, b, c, d;
};
struct modp_group {
math_mp_t gen; /* Generator */
math_mp_t p; /* Prime */
math_mp_t a, b, c, d;
};
/*
* This module provides access to the operations on the specified group
* and is absolutely free of any cryptographic devices. This is math :-).
*/
#define OAKLEY_GRP_1 1
#define OAKLEY_GRP_2 2
#define OAKLEY_GRP_3 3
#define OAKLEY_GRP_4 4
#define OAKLEY_GRP_5 5
#define OAKLEY_GRP_6 6
#define OAKLEY_GRP_7 7
#define OAKLEY_GRP_8 8
#define OAKLEY_GRP_9 9
#define OAKLEY_GRP_10 10
#define OAKLEY_GRP_11 11
#define OAKLEY_GRP_12 12
#define OAKLEY_GRP_13 13
#define OAKLEY_GRP_14 14
#define OAKLEY_GRP_15 15
#define OAKLEY_GRP_16 16
#define OAKLEY_GRP_17 17
#define OAKLEY_GRP_18 18
/* Describe preconfigured MODP groups */
/*
* The Generalized Number Field Sieve has an asymptotic running time
* of: O(exp(1.9223 * (ln q)^(1/3) (ln ln q)^(2/3))), where q is the
* group order, e.g. q = 2**768.
*/
struct modp_dscr oakley_modp[] =
{
{OAKLEY_GRP_1, 72, /* This group is insecure, only sufficient
* for DES */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_2, 82, /* This group is a bit better */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
"FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_5, 102,
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_14, 135, /* 2048 bit */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AACAA68FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_15, 170, /* 3072 bit */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
"43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_16, 195, /* 4096 bit */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
"FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_17, 220, /* 6144 bit */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
"12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
"0x02"
},
{OAKLEY_GRP_18, 250, /* 8192 bit */
"0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
"29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
"EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
"E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
"EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
"C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
"83655D23DCA3AD961C62F356208552BB9ED529077096966D"
"670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
"E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
"DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
"15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
"ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
"ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
"F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
"BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
"43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
"88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
"2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
"287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
"1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
"93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
"36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
"F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
"179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
"DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
"5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
"D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
"23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
"CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
"06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
"DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
"12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
"38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
"741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
"3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
"22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
"4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
"062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
"4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
"B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
"4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
"9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
"60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
"0x02"
},
};
/* Describe preconfigured EC2N groups */
/*
* Related collision-search methods can compute discrete logarithms
* in O(sqrt(r)), r being the subgroup order.
*/
struct ec2n_dscr oakley_ec2n[] = {
{ OAKLEY_GRP_3, 76, /* This group is also considered insecure
* (P1363) */
"0x0800000000000000000000004000000000000001",
"0x7b",
"0x00",
"0x7338f" },
{ OAKLEY_GRP_4, 91,
"0x020000000000000000000000000000200000000000000001",
"0x18",
"0x00",
"0x1ee9" },
};
/* XXX I want to get rid of the casting here. */
struct group groups[] = {
{
MODP, OAKLEY_GRP_1, 0, &oakley_modp[0], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
MODP, OAKLEY_GRP_2, 0, &oakley_modp[1], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
EC2N, OAKLEY_GRP_3, 0, &oakley_ec2n[0], 0, 0, 0, 0, 0,
(int (*) (struct group *)) ec2n_getlen,
(void (*) (struct group *, void *, u_int8_t *)) ec2n_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) ec2n_setraw,
(int (*) (struct group *, void *)) ec2n_setrandom,
(int (*) (struct group *, void *, void *, void *)) ec2n_operation,
(int (*) (struct group *, void *)) ec2n_validate_public
},
{
EC2N, OAKLEY_GRP_4, 0, &oakley_ec2n[1], 0, 0, 0, 0, 0,
(int (*) (struct group *)) ec2n_getlen,
(void (*) (struct group *, void *, u_int8_t *)) ec2n_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) ec2n_setraw,
(int (*) (struct group *, void *)) ec2n_setrandom,
(int (*) (struct group *, void *, void *, void *)) ec2n_operation,
(int (*) (struct group *, void *)) ec2n_validate_public
},
{
MODP, OAKLEY_GRP_5, 0, &oakley_modp[2], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
/* XXX Higher EC2N group go here... */
/* XXX group 6 to 13 are not yet defined (draft-ike-ecc) */
{
NOTYET, OAKLEY_GRP_6, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_7, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_8, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_9, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_10, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_11, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_12, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
NOTYET, OAKLEY_GRP_13, 0, NULL, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL
},
{
MODP, OAKLEY_GRP_14, 0, &oakley_modp[3], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
MODP, OAKLEY_GRP_15, 0, &oakley_modp[4], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
MODP, OAKLEY_GRP_16, 0, &oakley_modp[5], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
MODP, OAKLEY_GRP_17, 0, &oakley_modp[6], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
{
MODP, OAKLEY_GRP_18, 0, &oakley_modp[7], 0, 0, 0, 0, 0,
(int (*) (struct group *)) modp_getlen,
(void (*) (struct group *, void *, u_int8_t *)) modp_getraw,
(int (*) (struct group *, void *, u_int8_t *, int)) modp_setraw,
(int (*) (struct group *, void *)) modp_setrandom,
(int (*) (struct group *, void *, void *, void *)) modp_operation,
(int (*) (struct group *, void *)) modp_validate_public
},
};
/*
* Initialize the group structure for later use,
* this is done by converting the values given in the description
* and converting them to their native representation.
*/
void
group_init(void)
{
int i;
for (i = sizeof(groups) / sizeof(groups[0]) - 1; i >= 0; i--)
switch (groups[i].type) {
case EC2N: /* Initialize an Elliptic Curve over GF(2**n) */
ec2n_init(&groups[i]);
break;
case MODP: /* Initialize an over GF(p) */
modp_init(&groups[i]);
break;
case NOTYET: /* Not yet assigned, drop silently */
break;
default:
log_print("Unknown group type %d at index %d in "
"group_init().", groups[i].type, i);
break;
}
}
struct group *
group_get(u_int32_t id)
{
struct group *new, *clone;
if (id < 1 || id > (sizeof(groups) / sizeof(groups[0]))) {
log_print("group_get: group ID (%u) out of range", id);
return 0;
}
clone = &groups[id - 1];
new = malloc(sizeof *new);
if (!new) {
log_error("group_get: malloc (%lu) failed",
(unsigned long)sizeof *new);
return 0;
}
switch (clone->type) {
case EC2N:
new = ec2n_clone(new, clone);
break;
case MODP:
new = modp_clone(new, clone);
break;
default:
log_print("group_get: unknown group type %d", clone->type);
free(new);
return 0;
}
LOG_DBG((LOG_MISC, 70, "group_get: returning %p of group %d", new,
new->id));
return new;
}
void
group_free(struct group *grp)
{
switch (grp->type) {
case EC2N:
ec2n_free(grp);
break;
case MODP:
modp_free(grp);
break;
default:
log_print("group_free: unknown group type %d", grp->type);
break;
}
free(grp);
}
struct group *
modp_clone(struct group *new, struct group *clone)
{
struct modp_group *new_grp, *clone_grp = clone->group;
new_grp = malloc(sizeof *new_grp);
if (!new_grp) {
log_print("modp_clone: malloc (%lu) failed",
(unsigned long)sizeof *new_grp);
free(new);
return 0;
}
memcpy(new, clone, sizeof(struct group));
new->group = new_grp;
new_grp->p = BN_dup(clone_grp->p);
new_grp->gen = BN_dup(clone_grp->gen);
new_grp->a = BN_new();
new_grp->b = BN_new();
new_grp->c = BN_new();
new->gen = new_grp->gen;
new->a = new_grp->a;
new->b = new_grp->b;
new->c = new_grp->c;
return new;
}
void
modp_free(struct group *old)
{
struct modp_group *grp = old->group;
BN_clear_free(grp->p);
BN_clear_free(grp->gen);
BN_clear_free(grp->a);
BN_clear_free(grp->b);
BN_clear_free(grp->c);
free(grp);
}
void
modp_init(struct group *group)
{
struct modp_dscr *dscr = (struct modp_dscr *)group->group;
struct modp_group *grp;
grp = malloc(sizeof *grp);
if (!grp)
log_fatal("modp_init: malloc (%lu) failed",
(unsigned long)sizeof *grp);
group->bits = dscr->bits;
grp->p = BN_new();
BN_hex2bn(&grp->p, dscr->prime + 2);
grp->gen = BN_new();
BN_hex2bn(&grp->gen, dscr->gen + 2);
grp->a = BN_new();
grp->b = BN_new();
grp->c = BN_new();
group->gen = grp->gen;
group->a = grp->a;
group->b = grp->b;
group->c = grp->c;
group->group = grp;
}
struct group *
ec2n_clone(struct group *new, struct group *clone)
{
struct ec2n_group *new_grp, *clone_grp = clone->group;
new_grp = malloc(sizeof *new_grp);
if (!new_grp) {
log_error("ec2n_clone: malloc (%lu) failed",
(unsigned long)sizeof *new_grp);
free(new);
return 0;
}
memcpy(new, clone, sizeof(struct group));
new->group = new_grp;
ec2ng_init(new_grp->grp);
ec2np_init(new_grp->gen);
ec2np_init(new_grp->a);
ec2np_init(new_grp->b);
ec2np_init(new_grp->c);
if (ec2ng_set(new_grp->grp, clone_grp->grp))
goto fail;
if (ec2np_set(new_grp->gen, clone_grp->gen))
goto fail;
new->gen = new_grp->gen;
new->a = new_grp->a;
new->b = new_grp->b;
new->c = new_grp->c;
new->d = ((ec2np_ptr) new->a)->x;
return new;
fail:
ec2ng_clear(new_grp->grp);
ec2np_clear(new_grp->gen);
ec2np_clear(new_grp->a);
ec2np_clear(new_grp->b);
ec2np_clear(new_grp->c);
free(new_grp);
free(new);
return 0;
}
void
ec2n_free(struct group *old)
{
struct ec2n_group *grp = old->group;
ec2ng_clear(grp->grp);
ec2np_clear(grp->gen);
ec2np_clear(grp->a);
ec2np_clear(grp->b);
ec2np_clear(grp->c);
free(grp);
}
void
ec2n_init(struct group *group)
{
struct ec2n_dscr *dscr = (struct ec2n_dscr *)group->group;
struct ec2n_group *grp;
grp = malloc(sizeof *grp);
if (!grp)
log_fatal("ec2n_init: malloc (%lu) failed",
(unsigned long)sizeof *grp);
group->bits = dscr->bits;
ec2ng_init(grp->grp);
ec2np_init(grp->gen);
ec2np_init(grp->a);
ec2np_init(grp->b);
ec2np_init(grp->c);
if (ec2ng_set_p_str(grp->grp, dscr->polynomial))
goto fail;
grp->grp->p->bits = b2n_sigbit(grp->grp->p);
if (ec2ng_set_a_str(grp->grp, dscr->a))
goto fail;
if (ec2ng_set_b_str(grp->grp, dscr->b))
goto fail;
if (ec2np_set_x_str(grp->gen, dscr->gen_x))
goto fail;
if (ec2np_find_y(grp->gen, grp->grp))
goto fail;
/* Sanity check */
if (!ec2np_ison(grp->gen, grp->grp))
log_fatal("ec2n_init: generator is not on curve");
group->gen = grp->gen;
group->a = grp->a;
group->b = grp->b;
group->c = grp->c;
group->d = ((ec2np_ptr) group->a)->x;
group->group = grp;
return;
fail:
log_fatal("ec2n_init: general failure");
}
int
modp_getlen(struct group *group)
{
struct modp_group *grp = (struct modp_group *)group->group;
return BN_num_bytes(grp->p);
}
void
modp_getraw(struct group *grp, math_mp_t v, u_int8_t *d)
{
math_mp_t a;
int len;
len = grp->getlen(grp);
/* XXX bn2bin? */
a = BN_dup(v);
while (len-- > 0)
d[len] = BN_div_word(a, 256);
BN_clear_free(a);
}
int
modp_setraw(struct group *group, math_mp_t d, u_int8_t *s, int l)
{
if (BN_bin2bn(s, l, d) == NULL)
return -1;
return 0;
}
int
modp_setrandom(struct group *grp, math_mp_t d)
{
int i, l = grp->getlen(grp);
u_int32_t tmp = 0;
BN_set_word(d, 0);
for (i = 0; i < l; i++) {
if (i % 4)
tmp = rand_32();
BN_lshift(d, d, 8);
BN_add_word(d, tmp & 0xFF);
tmp >>= 8;
}
return 0;
}
int
modp_operation(struct group *group, math_mp_t d, math_mp_t a, math_mp_t e)
{
struct modp_group *grp = (struct modp_group *)group->group;
BN_CTX *ctx = BN_CTX_new();
BN_mod_exp(d, a, e, grp->p, ctx);
BN_CTX_free(ctx);
return 0;
}
int
modp_validate_public(struct group *group, math_mp_t pub_exp)
{
struct modp_group *grp = (struct modp_group *)group->group;
int i, len, bits_set;
math_mp_t tmp;
/*
* Sanity checks from RFC2412 section 2.3.1.1:
* Ensure that peer does not send us <0, 0, 1, p-1 or >= p
*/
if (BN_cmp(pub_exp, BN_value_one()) != 1) /* pub_exp <= 1 */
return -1;
if ((tmp = BN_new()) == NULL)
return -1;
if (!BN_sub(tmp, grp->p, BN_value_one()) ||
BN_cmp(pub_exp, tmp) != -1) { /* pub_exp > p-2 */
BN_clear_free(tmp);
return -1;
}
BN_clear_free(tmp);
/*
* Another sanity check: when the generator is 2 and the
* population count of the public exponent is 1, then
* computing log_g(pub_exp) is trivial.
*/
len = BN_num_bits(pub_exp);
for (bits_set = i = 0; i < len; i++) {
if (BN_is_bit_set(pub_exp, i))
bits_set++;
}
if (bits_set <= 1)
return -1;
return 0;
}
int
ec2n_getlen(struct group *group)
{
struct ec2n_group *grp = (struct ec2n_group *)group->group;
int bits = b2n_sigbit(grp->grp->p) - 1;
return (7 + bits) >> 3;
}
void
ec2n_getraw(struct group *group, ec2np_ptr xo, u_int8_t *e)
{
struct ec2n_group *grp = (struct ec2n_group *) group->group;
int chunks, bytes, i, j;
b2n_ptr x = xo->x;
CHUNK_TYPE tmp;
bytes = b2n_sigbit(grp->grp->p) - 1;
chunks = (CHUNK_MASK + bytes) >> CHUNK_SHIFTS;
bytes = ((7 + (bytes & CHUNK_MASK)) >> 3);
for (i = chunks - 1; i >= 0; i--) {
tmp = (i >= x->chunks ? 0 : x->limp[i]);
for (j = (i == chunks - 1 ? bytes : CHUNK_BYTES) - 1; j >= 0;
j--) {
e[j] = tmp & 0xff;
tmp >>= 8;
}
e += (i == chunks - 1 ? bytes : CHUNK_BYTES);
}
}
int
ec2n_setraw(struct group *grp, ec2np_ptr out, u_int8_t *s, int l)
{
int len, bytes, i, j;
b2n_ptr outx = out->x;
CHUNK_TYPE tmp;
len = (CHUNK_BYTES - 1 + l) / CHUNK_BYTES;
if (b2n_resize(outx, len))
return -1;
bytes = ((l - 1) % CHUNK_BYTES) + 1;
for (i = len - 1; i >= 0; i--) {
tmp = 0;
for (j = (i == len - 1 ? bytes : CHUNK_BYTES); j > 0; j--) {
tmp <<= 8;
tmp |= *s++;
}
outx->limp[i] = tmp;
}
return 0;
}
int
ec2n_setrandom(struct group *group, ec2np_ptr x)
{
b2n_ptr d = x->x;
struct ec2n_group *grp = (struct ec2n_group *) group->group;
return b2n_random(d, b2n_sigbit(grp->grp->p) - 1);
}
/*
* This is an attempt at operation abstraction. It can happen
* that we need to initialize the y variable for the operation
* to proceed correctly. When this is the case operation has
* to supply the variable 'a' with the chunks of the Y coordinate
* set to zero.
*/
int
ec2n_operation(struct group *grp, ec2np_ptr d, ec2np_ptr a, ec2np_ptr e)
{
b2n_ptr ex = e->x;
struct ec2n_group *group = (struct ec2n_group *)grp->group;
if (a->y->chunks == 0)
if (ec2np_find_y(a, group->grp))
return -1;
return ec2np_mul(d, a, ex, group->grp);
}
int
ec2n_validate_public(struct group *grp, ec2np_ptr p)
{
/* XXX: needs similar checks to modp_validate_public() */
return 0;
}