summaryrefslogtreecommitdiff
path: root/usr/src/common/bignum/bignum.h
blob: f2389cb5b75f4bd9c511090edd8cf436d6817434 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 */

#ifndef _BIGNUM_H
#define	_BIGNUM_H

#ifdef	__cplusplus
extern "C" {
#endif

#include <sys/types.h>

#if defined(__sparcv9) || defined(__amd64) /* 64-bit chunk size */
#ifndef UMUL64
#define	UMUL64	/* 64-bit multiplication results are supported */
#endif
#else
#define	BIGNUM_CHUNK_32
#endif


#define	BITSINBYTE	8

/* Bignum "digits" (aka "chunks" or "words") are either 32- or 64-bits */
#ifdef BIGNUM_CHUNK_32
#define	BIG_CHUNK_SIZE		32
#define	BIG_CHUNK_TYPE		uint32_t
#define	BIG_CHUNK_TYPE_SIGNED	int32_t
#define	BIG_CHUNK_HIGHBIT	0x80000000
#define	BIG_CHUNK_ALLBITS	0xffffffff
#define	BIG_CHUNK_LOWHALFBITS	0xffff
#define	BIG_CHUNK_HALF_HIGHBIT	0x8000

#else
#define	BIG_CHUNK_SIZE		64
#define	BIG_CHUNK_TYPE		uint64_t
#define	BIG_CHUNK_TYPE_SIGNED	int64_t
#define	BIG_CHUNK_HIGHBIT	0x8000000000000000ULL
#define	BIG_CHUNK_ALLBITS	0xffffffffffffffffULL
#define	BIG_CHUNK_LOWHALFBITS	0xffffffffULL
#define	BIG_CHUNK_HALF_HIGHBIT	0x80000000ULL
#endif

#define	BITLEN2BIGNUMLEN(x)	((x) > 0 ? \
				((((x) - 1) / BIG_CHUNK_SIZE) + 1) : 0)
#define	CHARLEN2BIGNUMLEN(x)	((x) > 0 ? \
				((((x) - 1) / sizeof (BIG_CHUNK_TYPE)) + 1) : 0)

#define	BIGNUM_WORDSIZE	(BIG_CHUNK_SIZE / BITSINBYTE)  /* word size in bytes */
#define	BIG_CHUNKS_FOR_160BITS	BITLEN2BIGNUMLEN(160)


/*
 * leading 0's are permitted
 * 0 should be represented by size>=1, size>=len>=1, sign=1,
 * value[i]=0 for 0<i<len
 */
typedef struct {
	/* size and len in units of BIG_CHUNK_TYPE words  */
	uint32_t	size;	/* size of memory allocated for value  */
	uint32_t	len;	/* number of valid data words in value */
	int		sign;	/* 1 for nonnegative, -1 for negative  */
	int		malloced; /* 1 if value was malloced, 0 if not */
	BIG_CHUNK_TYPE *value;
} BIGNUM;

#define	BIGTMPSIZE 65

#define	BIG_TRUE 1
#define	BIG_FALSE 0

typedef int BIG_ERR_CODE;

/* error codes */
#define	BIG_OK 0
#define	BIG_NO_MEM -1
#define	BIG_INVALID_ARGS -2
#define	BIG_DIV_BY_0 -3
#define	BIG_NO_RANDOM -4
#define	BIG_GENERAL_ERR	-5
#define	BIG_TEST_FAILED -6
#define	BIG_BUFFER_TOO_SMALL -7


#define	arraysize(x) (sizeof (x) / sizeof (x[0]))

typedef BIG_ERR_CODE (*big_modexp_ncp_func_ptr)(BIGNUM *result,
    BIGNUM *ma, BIGNUM *e, BIGNUM *n,
    BIGNUM *tmp, BIG_CHUNK_TYPE n0, void *ncp, void *req);

typedef struct {
	big_modexp_ncp_func_ptr	func;
	void			*ncp;
	void 			*reqp;
} big_modexp_ncp_info_t;


#ifdef USE_FLOATING_POINT
void conv_d16_to_i32(uint32_t *i32, double *d16, int64_t *tmp, int ilen);
void conv_i32_to_d32(double *d32, uint32_t *i32, int len);
void conv_i32_to_d16(double *d16, uint32_t *i32, int len);
void conv_i32_to_d32_and_d16(double *d32, double *d16,
    uint32_t *i32, int len);
void mont_mulf_noconv(uint32_t *result, double *dm1, double *dm2, double *dt,
    double *dn, uint32_t *nint, int nlen, double dn0);
#endif /* USE_FLOATING_POINT */

extern BIGNUM big_One;
extern BIGNUM big_Two;

void printbignum(char *aname, BIGNUM *a);

BIG_ERR_CODE big_init(BIGNUM *number, int size);
BIG_ERR_CODE big_extend(BIGNUM *number, int size);
void big_finish(BIGNUM *number);
void bytestring2bignum(BIGNUM *bn, uchar_t *kn, size_t len);
void bignum2bytestring(uchar_t *kn, BIGNUM *bn, size_t len);
BIG_ERR_CODE big_mont_rr(BIGNUM *result, BIGNUM *n);
BIG_ERR_CODE big_modexp(BIGNUM *result, BIGNUM *a, BIGNUM *e,
    BIGNUM *n, BIGNUM *n_rr);
BIG_ERR_CODE big_modexp_ext(BIGNUM *result, BIGNUM *a, BIGNUM *e,
    BIGNUM *n, BIGNUM *n_rr, big_modexp_ncp_info_t *info);
BIG_ERR_CODE big_modexp_crt(BIGNUM *result, BIGNUM *a, BIGNUM *dmodpminus1,
    BIGNUM *dmodqminus1, BIGNUM *p, BIGNUM *q, BIGNUM *pinvmodq,
    BIGNUM *p_rr, BIGNUM *q_rr);
BIG_ERR_CODE big_modexp_crt_ext(BIGNUM *result, BIGNUM *a, BIGNUM *dmodpminus1,
    BIGNUM *dmodqminus1, BIGNUM *p, BIGNUM *q, BIGNUM *pinvmodq,
    BIGNUM *p_rr, BIGNUM *q_rr, big_modexp_ncp_info_t *info);
int big_cmp_abs(BIGNUM *a, BIGNUM *b);
BIG_ERR_CODE big_random(BIGNUM *r, size_t length, int (*rfunc)(void *, size_t));
BIG_ERR_CODE big_div_pos(BIGNUM *result, BIGNUM *remainder,
    BIGNUM *aa, BIGNUM *bb);
BIG_ERR_CODE big_ext_gcd_pos(BIGNUM *gcd, BIGNUM *cm, BIGNUM *ce,
    BIGNUM *m, BIGNUM *e);
BIG_ERR_CODE big_add(BIGNUM *result, BIGNUM *aa, BIGNUM *bb);
BIG_ERR_CODE big_add_abs(BIGNUM *result, BIGNUM *aa, BIGNUM *bb);
BIG_ERR_CODE big_mul(BIGNUM *result, BIGNUM *aa, BIGNUM *bb);
void big_shiftright(BIGNUM *result, BIGNUM *aa, int offs);
BIG_ERR_CODE big_nextprime_pos(BIGNUM *result, BIGNUM *n);
BIG_ERR_CODE big_nextprime_pos_ext(BIGNUM *result, BIGNUM *n,
    big_modexp_ncp_info_t *info);
BIG_ERR_CODE big_sub_pos(BIGNUM *result, BIGNUM *aa, BIGNUM *bb);
BIG_ERR_CODE big_copy(BIGNUM *dest, BIGNUM *src);
BIG_ERR_CODE big_sub(BIGNUM *result, BIGNUM *aa, BIGNUM *bb);
int big_bitlength(BIGNUM *n);
BIG_ERR_CODE big_init1(BIGNUM *number, int size,
    BIG_CHUNK_TYPE *buf, int bufsize);
BIG_ERR_CODE big_mont_mul(BIGNUM *ret,
    BIGNUM *a, BIGNUM *b, BIGNUM *n, BIG_CHUNK_TYPE n0);
int big_is_zero(BIGNUM *n);
BIG_CHUNK_TYPE big_n0(BIG_CHUNK_TYPE n);


#if defined(HWCAP)

#if (BIG_CHUNK_SIZE != 32)
#error HWCAP works only with 32-bit bignum chunks
#endif

#define	BIG_MUL_SET_VEC(r, a, len, digit) \
	(*big_mul_set_vec_impl)(r, a, len, digit)
#define	BIG_MUL_ADD_VEC(r, a, len, digit) \
	(*big_mul_add_vec_impl)(r, a, len, digit)
#define	BIG_MUL_VEC(r, a, alen, b, blen) \
	(*big_mul_vec_impl)(r, a, alen, b, blen)
#define	BIG_SQR_VEC(r, a, len) \
	(*big_sqr_vec_impl)(r, a, len)

extern BIG_CHUNK_TYPE (*big_mul_set_vec_impl)
	(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int len, BIG_CHUNK_TYPE digit);
extern BIG_CHUNK_TYPE (*big_mul_add_vec_impl)
	(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int len, BIG_CHUNK_TYPE digit);
extern void (*big_mul_vec_impl)
	(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int alen, BIG_CHUNK_TYPE *b,
	    int blen);
extern void (*big_sqr_vec_impl)
	(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int len);

#else /* ! HWCAP */

#define	BIG_MUL_SET_VEC(r, a, len, digit) big_mul_set_vec(r, a, len, digit)
#define	BIG_MUL_ADD_VEC(r, a, len, digit) big_mul_add_vec(r, a, len, digit)
#define	BIG_MUL_VEC(r, a, alen, b, blen) big_mul_vec(r, a, alen, b, blen)
#define	BIG_SQR_VEC(r, a, len) big_sqr_vec(r, a, len)

extern BIG_CHUNK_TYPE big_mul_set_vec(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a,
    int len, BIG_CHUNK_TYPE d);
extern BIG_CHUNK_TYPE big_mul_add_vec(BIG_CHUNK_TYPE *r,
    BIG_CHUNK_TYPE *a, int len, BIG_CHUNK_TYPE d);
extern void big_mul_vec(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int alen,
    BIG_CHUNK_TYPE *b, int blen);
extern void big_sqr_vec(BIG_CHUNK_TYPE *r, BIG_CHUNK_TYPE *a, int len);

#endif /* HWCAP */

#ifdef	__cplusplus
}
#endif

#endif	/* _BIGNUM_H */