openssl 2.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of openssl might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CONTRIBUTING.md +130 -0
- data/History.md +118 -0
- data/LICENSE.txt +56 -0
- data/README.md +70 -0
- data/ext/openssl/deprecation.rb +26 -0
- data/ext/openssl/extconf.rb +158 -0
- data/ext/openssl/openssl_missing.c +173 -0
- data/ext/openssl/openssl_missing.h +244 -0
- data/ext/openssl/ossl.c +1201 -0
- data/ext/openssl/ossl.h +222 -0
- data/ext/openssl/ossl_asn1.c +1992 -0
- data/ext/openssl/ossl_asn1.h +66 -0
- data/ext/openssl/ossl_bio.c +87 -0
- data/ext/openssl/ossl_bio.h +19 -0
- data/ext/openssl/ossl_bn.c +1153 -0
- data/ext/openssl/ossl_bn.h +23 -0
- data/ext/openssl/ossl_cipher.c +1085 -0
- data/ext/openssl/ossl_cipher.h +20 -0
- data/ext/openssl/ossl_config.c +89 -0
- data/ext/openssl/ossl_config.h +19 -0
- data/ext/openssl/ossl_digest.c +453 -0
- data/ext/openssl/ossl_digest.h +20 -0
- data/ext/openssl/ossl_engine.c +580 -0
- data/ext/openssl/ossl_engine.h +19 -0
- data/ext/openssl/ossl_hmac.c +398 -0
- data/ext/openssl/ossl_hmac.h +18 -0
- data/ext/openssl/ossl_ns_spki.c +406 -0
- data/ext/openssl/ossl_ns_spki.h +19 -0
- data/ext/openssl/ossl_ocsp.c +2013 -0
- data/ext/openssl/ossl_ocsp.h +23 -0
- data/ext/openssl/ossl_pkcs12.c +259 -0
- data/ext/openssl/ossl_pkcs12.h +13 -0
- data/ext/openssl/ossl_pkcs5.c +180 -0
- data/ext/openssl/ossl_pkcs5.h +6 -0
- data/ext/openssl/ossl_pkcs7.c +1125 -0
- data/ext/openssl/ossl_pkcs7.h +20 -0
- data/ext/openssl/ossl_pkey.c +435 -0
- data/ext/openssl/ossl_pkey.h +245 -0
- data/ext/openssl/ossl_pkey_dh.c +650 -0
- data/ext/openssl/ossl_pkey_dsa.c +672 -0
- data/ext/openssl/ossl_pkey_ec.c +1899 -0
- data/ext/openssl/ossl_pkey_rsa.c +768 -0
- data/ext/openssl/ossl_rand.c +238 -0
- data/ext/openssl/ossl_rand.h +18 -0
- data/ext/openssl/ossl_ssl.c +2679 -0
- data/ext/openssl/ossl_ssl.h +41 -0
- data/ext/openssl/ossl_ssl_session.c +352 -0
- data/ext/openssl/ossl_version.h +15 -0
- data/ext/openssl/ossl_x509.c +186 -0
- data/ext/openssl/ossl_x509.h +119 -0
- data/ext/openssl/ossl_x509attr.c +328 -0
- data/ext/openssl/ossl_x509cert.c +860 -0
- data/ext/openssl/ossl_x509crl.c +565 -0
- data/ext/openssl/ossl_x509ext.c +480 -0
- data/ext/openssl/ossl_x509name.c +547 -0
- data/ext/openssl/ossl_x509req.c +492 -0
- data/ext/openssl/ossl_x509revoked.c +279 -0
- data/ext/openssl/ossl_x509store.c +846 -0
- data/ext/openssl/ruby_missing.h +32 -0
- data/lib/openssl.rb +21 -0
- data/lib/openssl/bn.rb +39 -0
- data/lib/openssl/buffering.rb +451 -0
- data/lib/openssl/cipher.rb +67 -0
- data/lib/openssl/config.rb +473 -0
- data/lib/openssl/digest.rb +78 -0
- data/lib/openssl/pkey.rb +44 -0
- data/lib/openssl/ssl.rb +416 -0
- data/lib/openssl/x509.rb +176 -0
- metadata +178 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' team members
|
3
|
+
* Copyright (C) 2003
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#if !defined(_OSSL_ASN1_H_)
|
11
|
+
#define _OSSL_ASN1_H_
|
12
|
+
|
13
|
+
/*
|
14
|
+
* ASN1_DATE conversions
|
15
|
+
*/
|
16
|
+
VALUE asn1time_to_time(const ASN1_TIME *);
|
17
|
+
#if defined(HAVE_ASN1_TIME_ADJ)
|
18
|
+
/* Splits VALUE to seconds and offset days. VALUE is typically a Time or an
|
19
|
+
* Integer. This is used when updating ASN1_*TIME with ASN1_TIME_adj() or
|
20
|
+
* X509_time_adj_ex(). We can't use ASN1_TIME_set() and X509_time_adj() because
|
21
|
+
* they have the Year 2038 issue on sizeof(time_t) == 4 environment */
|
22
|
+
void ossl_time_split(VALUE, time_t *, int *);
|
23
|
+
#else
|
24
|
+
time_t time_to_time_t(VALUE);
|
25
|
+
#endif
|
26
|
+
|
27
|
+
/*
|
28
|
+
* ASN1_STRING conversions
|
29
|
+
*/
|
30
|
+
VALUE asn1str_to_str(const ASN1_STRING *);
|
31
|
+
|
32
|
+
/*
|
33
|
+
* ASN1_INTEGER conversions
|
34
|
+
*/
|
35
|
+
VALUE asn1integer_to_num(const ASN1_INTEGER *);
|
36
|
+
ASN1_INTEGER *num_to_asn1integer(VALUE, ASN1_INTEGER *);
|
37
|
+
|
38
|
+
/*
|
39
|
+
* ASN1 module
|
40
|
+
*/
|
41
|
+
extern VALUE mASN1;
|
42
|
+
extern VALUE eASN1Error;
|
43
|
+
|
44
|
+
extern VALUE cASN1Data;
|
45
|
+
extern VALUE cASN1Primitive;
|
46
|
+
extern VALUE cASN1Constructive;
|
47
|
+
|
48
|
+
extern VALUE cASN1Boolean; /* BOOLEAN */
|
49
|
+
extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */
|
50
|
+
extern VALUE cASN1BitString; /* BIT STRING */
|
51
|
+
extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */
|
52
|
+
extern VALUE cASN1NumericString, cASN1PrintableString;
|
53
|
+
extern VALUE cASN1T61String, cASN1VideotexString;
|
54
|
+
extern VALUE cASN1IA5String, cASN1GraphicString;
|
55
|
+
extern VALUE cASN1ISO64String, cASN1GeneralString;
|
56
|
+
extern VALUE cASN1UniversalString, cASN1BMPString;
|
57
|
+
extern VALUE cASN1Null; /* NULL */
|
58
|
+
extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */
|
59
|
+
extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */
|
60
|
+
extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */
|
61
|
+
|
62
|
+
ASN1_TYPE *ossl_asn1_get_asn1type(VALUE);
|
63
|
+
|
64
|
+
void Init_ossl_asn1(void);
|
65
|
+
|
66
|
+
#endif
|
@@ -0,0 +1,87 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' team members
|
3
|
+
* Copyright (C) 2003
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#include "ossl.h"
|
11
|
+
#ifdef HAVE_UNISTD_H
|
12
|
+
#include <unistd.h>
|
13
|
+
#endif
|
14
|
+
|
15
|
+
BIO *
|
16
|
+
ossl_obj2bio(VALUE obj)
|
17
|
+
{
|
18
|
+
BIO *bio;
|
19
|
+
|
20
|
+
if (RB_TYPE_P(obj, T_FILE)) {
|
21
|
+
rb_io_t *fptr;
|
22
|
+
FILE *fp;
|
23
|
+
int fd;
|
24
|
+
|
25
|
+
GetOpenFile(obj, fptr);
|
26
|
+
rb_io_check_readable(fptr);
|
27
|
+
if ((fd = rb_cloexec_dup(FPTR_TO_FD(fptr))) < 0){
|
28
|
+
rb_sys_fail(0);
|
29
|
+
}
|
30
|
+
rb_update_max_fd(fd);
|
31
|
+
if (!(fp = fdopen(fd, "r"))){
|
32
|
+
int e = errno;
|
33
|
+
close(fd);
|
34
|
+
rb_syserr_fail(e, 0);
|
35
|
+
}
|
36
|
+
if (!(bio = BIO_new_fp(fp, BIO_CLOSE))){
|
37
|
+
fclose(fp);
|
38
|
+
ossl_raise(eOSSLError, NULL);
|
39
|
+
}
|
40
|
+
}
|
41
|
+
else {
|
42
|
+
StringValue(obj);
|
43
|
+
bio = BIO_new_mem_buf(RSTRING_PTR(obj), RSTRING_LENINT(obj));
|
44
|
+
if (!bio) ossl_raise(eOSSLError, NULL);
|
45
|
+
}
|
46
|
+
|
47
|
+
return bio;
|
48
|
+
}
|
49
|
+
|
50
|
+
BIO *
|
51
|
+
ossl_protect_obj2bio(VALUE obj, int *status)
|
52
|
+
{
|
53
|
+
BIO *ret = NULL;
|
54
|
+
ret = (BIO*)rb_protect((VALUE (*)(VALUE))ossl_obj2bio, obj, status);
|
55
|
+
return ret;
|
56
|
+
}
|
57
|
+
|
58
|
+
VALUE
|
59
|
+
ossl_membio2str0(BIO *bio)
|
60
|
+
{
|
61
|
+
VALUE ret;
|
62
|
+
BUF_MEM *buf;
|
63
|
+
|
64
|
+
BIO_get_mem_ptr(bio, &buf);
|
65
|
+
ret = rb_str_new(buf->data, buf->length);
|
66
|
+
|
67
|
+
return ret;
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE
|
71
|
+
ossl_protect_membio2str(BIO *bio, int *status)
|
72
|
+
{
|
73
|
+
return rb_protect((VALUE (*)(VALUE))ossl_membio2str0, (VALUE)bio, status);
|
74
|
+
}
|
75
|
+
|
76
|
+
VALUE
|
77
|
+
ossl_membio2str(BIO *bio)
|
78
|
+
{
|
79
|
+
VALUE ret;
|
80
|
+
int status = 0;
|
81
|
+
|
82
|
+
ret = ossl_protect_membio2str(bio, &status);
|
83
|
+
BIO_free(bio);
|
84
|
+
if(status) rb_jump_tag(status);
|
85
|
+
|
86
|
+
return ret;
|
87
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' team members
|
3
|
+
* Copyright (C) 2003
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
#if !defined(_OSSL_BIO_H_)
|
11
|
+
#define _OSSL_BIO_H_
|
12
|
+
|
13
|
+
BIO *ossl_obj2bio(VALUE);
|
14
|
+
BIO *ossl_protect_obj2bio(VALUE,int*);
|
15
|
+
VALUE ossl_membio2str0(BIO*);
|
16
|
+
VALUE ossl_membio2str(BIO*);
|
17
|
+
VALUE ossl_protect_membio2str(BIO*,int*);
|
18
|
+
|
19
|
+
#endif
|
@@ -0,0 +1,1153 @@
|
|
1
|
+
/*
|
2
|
+
* 'OpenSSL for Ruby' project
|
3
|
+
* Copyright (C) 2001-2002 Technorama team <oss-ruby@technorama.net>
|
4
|
+
* All rights reserved.
|
5
|
+
*/
|
6
|
+
/*
|
7
|
+
* This program is licensed under the same licence as Ruby.
|
8
|
+
* (See the file 'LICENCE'.)
|
9
|
+
*/
|
10
|
+
/* modified by Michal Rokos <m.rokos@sh.cvut.cz> */
|
11
|
+
#include "ossl.h"
|
12
|
+
|
13
|
+
#define NewBN(klass) \
|
14
|
+
TypedData_Wrap_Struct((klass), &ossl_bn_type, 0)
|
15
|
+
#define SetBN(obj, bn) do { \
|
16
|
+
if (!(bn)) { \
|
17
|
+
ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
|
18
|
+
} \
|
19
|
+
RTYPEDDATA_DATA(obj) = (bn); \
|
20
|
+
} while (0)
|
21
|
+
|
22
|
+
#define GetBN(obj, bn) do { \
|
23
|
+
TypedData_Get_Struct((obj), BIGNUM, &ossl_bn_type, (bn)); \
|
24
|
+
if (!(bn)) { \
|
25
|
+
ossl_raise(rb_eRuntimeError, "BN wasn't initialized!"); \
|
26
|
+
} \
|
27
|
+
} while (0)
|
28
|
+
|
29
|
+
#define SafeGetBN(obj, bn) do { \
|
30
|
+
OSSL_Check_Kind((obj), cBN); \
|
31
|
+
GetBN((obj), (bn)); \
|
32
|
+
} while (0)
|
33
|
+
|
34
|
+
static void
|
35
|
+
ossl_bn_free(void *ptr)
|
36
|
+
{
|
37
|
+
BN_clear_free(ptr);
|
38
|
+
}
|
39
|
+
|
40
|
+
static const rb_data_type_t ossl_bn_type = {
|
41
|
+
"OpenSSL/BN",
|
42
|
+
{
|
43
|
+
0, ossl_bn_free,
|
44
|
+
},
|
45
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY,
|
46
|
+
};
|
47
|
+
|
48
|
+
/*
|
49
|
+
* Classes
|
50
|
+
*/
|
51
|
+
VALUE cBN;
|
52
|
+
|
53
|
+
/* Document-class: OpenSSL::BNError
|
54
|
+
*
|
55
|
+
* Generic Error for all of OpenSSL::BN (big num)
|
56
|
+
*/
|
57
|
+
VALUE eBNError;
|
58
|
+
|
59
|
+
/*
|
60
|
+
* Public
|
61
|
+
*/
|
62
|
+
VALUE
|
63
|
+
ossl_bn_new(const BIGNUM *bn)
|
64
|
+
{
|
65
|
+
BIGNUM *newbn;
|
66
|
+
VALUE obj;
|
67
|
+
|
68
|
+
obj = NewBN(cBN);
|
69
|
+
newbn = bn ? BN_dup(bn) : BN_new();
|
70
|
+
if (!newbn) {
|
71
|
+
ossl_raise(eBNError, NULL);
|
72
|
+
}
|
73
|
+
SetBN(obj, newbn);
|
74
|
+
|
75
|
+
return obj;
|
76
|
+
}
|
77
|
+
|
78
|
+
static BIGNUM *
|
79
|
+
integer_to_bnptr(VALUE obj, BIGNUM *orig)
|
80
|
+
{
|
81
|
+
BIGNUM *bn;
|
82
|
+
|
83
|
+
if (FIXNUM_P(obj)) {
|
84
|
+
long i;
|
85
|
+
unsigned char bin[sizeof(long)];
|
86
|
+
long n = FIX2LONG(obj);
|
87
|
+
unsigned long un = labs(n);
|
88
|
+
|
89
|
+
for (i = sizeof(long) - 1; 0 <= i; i--) {
|
90
|
+
bin[i] = un & 0xff;
|
91
|
+
un >>= 8;
|
92
|
+
}
|
93
|
+
|
94
|
+
bn = BN_bin2bn(bin, sizeof(bin), orig);
|
95
|
+
if (!bn)
|
96
|
+
ossl_raise(eBNError, "BN_bin2bn");
|
97
|
+
if (n < 0)
|
98
|
+
BN_set_negative(bn, 1);
|
99
|
+
}
|
100
|
+
else { /* assuming Bignum */
|
101
|
+
size_t len = rb_absint_size(obj, NULL);
|
102
|
+
unsigned char *bin;
|
103
|
+
VALUE buf;
|
104
|
+
int sign;
|
105
|
+
|
106
|
+
if (INT_MAX < len) {
|
107
|
+
rb_raise(eBNError, "bignum too long");
|
108
|
+
}
|
109
|
+
bin = (unsigned char*)ALLOCV_N(unsigned char, buf, len);
|
110
|
+
sign = rb_integer_pack(obj, bin, len, 1, 0, INTEGER_PACK_BIG_ENDIAN);
|
111
|
+
|
112
|
+
bn = BN_bin2bn(bin, (int)len, orig);
|
113
|
+
ALLOCV_END(buf);
|
114
|
+
if (!bn)
|
115
|
+
ossl_raise(eBNError, "BN_bin2bn");
|
116
|
+
if (sign < 0)
|
117
|
+
BN_set_negative(bn, 1);
|
118
|
+
}
|
119
|
+
|
120
|
+
return bn;
|
121
|
+
}
|
122
|
+
|
123
|
+
static BIGNUM *
|
124
|
+
try_convert_to_bnptr(VALUE obj)
|
125
|
+
{
|
126
|
+
BIGNUM *bn = NULL;
|
127
|
+
VALUE newobj;
|
128
|
+
|
129
|
+
if (rb_obj_is_kind_of(obj, cBN)) {
|
130
|
+
GetBN(obj, bn);
|
131
|
+
}
|
132
|
+
else if (RB_INTEGER_TYPE_P(obj)) {
|
133
|
+
newobj = NewBN(cBN); /* Handle potencial mem leaks */
|
134
|
+
bn = integer_to_bnptr(obj, NULL);
|
135
|
+
SetBN(newobj, bn);
|
136
|
+
}
|
137
|
+
|
138
|
+
return bn;
|
139
|
+
}
|
140
|
+
|
141
|
+
BIGNUM *
|
142
|
+
GetBNPtr(VALUE obj)
|
143
|
+
{
|
144
|
+
BIGNUM *bn = try_convert_to_bnptr(obj);
|
145
|
+
if (!bn)
|
146
|
+
ossl_raise(rb_eTypeError, "Cannot convert into OpenSSL::BN");
|
147
|
+
|
148
|
+
return bn;
|
149
|
+
}
|
150
|
+
|
151
|
+
/*
|
152
|
+
* Private
|
153
|
+
*/
|
154
|
+
/*
|
155
|
+
* BN_CTX - is used in more difficult math. ops
|
156
|
+
* (Why just 1? Because Ruby itself isn't thread safe,
|
157
|
+
* we don't need to care about threads)
|
158
|
+
*/
|
159
|
+
BN_CTX *ossl_bn_ctx;
|
160
|
+
|
161
|
+
static VALUE
|
162
|
+
ossl_bn_alloc(VALUE klass)
|
163
|
+
{
|
164
|
+
BIGNUM *bn;
|
165
|
+
VALUE obj = NewBN(klass);
|
166
|
+
|
167
|
+
if (!(bn = BN_new())) {
|
168
|
+
ossl_raise(eBNError, NULL);
|
169
|
+
}
|
170
|
+
SetBN(obj, bn);
|
171
|
+
|
172
|
+
return obj;
|
173
|
+
}
|
174
|
+
|
175
|
+
/* Document-method: OpenSSL::BN.new
|
176
|
+
*
|
177
|
+
* call-seq:
|
178
|
+
* OpenSSL::BN.new => aBN
|
179
|
+
* OpenSSL::BN.new(bn) => aBN
|
180
|
+
* OpenSSL::BN.new(integer) => aBN
|
181
|
+
* OpenSSL::BN.new(string) => aBN
|
182
|
+
* OpenSSL::BN.new(string, 0 | 2 | 10 | 16) => aBN
|
183
|
+
*
|
184
|
+
* Construct a new OpenSSL BigNum object.
|
185
|
+
*/
|
186
|
+
static VALUE
|
187
|
+
ossl_bn_initialize(int argc, VALUE *argv, VALUE self)
|
188
|
+
{
|
189
|
+
BIGNUM *bn;
|
190
|
+
VALUE str, bs;
|
191
|
+
int base = 10;
|
192
|
+
|
193
|
+
if (rb_scan_args(argc, argv, "11", &str, &bs) == 2) {
|
194
|
+
base = NUM2INT(bs);
|
195
|
+
}
|
196
|
+
|
197
|
+
if (RB_INTEGER_TYPE_P(str)) {
|
198
|
+
GetBN(self, bn);
|
199
|
+
integer_to_bnptr(str, bn);
|
200
|
+
|
201
|
+
return self;
|
202
|
+
}
|
203
|
+
|
204
|
+
if (RTEST(rb_obj_is_kind_of(str, cBN))) {
|
205
|
+
BIGNUM *other;
|
206
|
+
|
207
|
+
GetBN(self, bn);
|
208
|
+
GetBN(str, other); /* Safe - we checked kind_of? above */
|
209
|
+
if (!BN_copy(bn, other)) {
|
210
|
+
ossl_raise(eBNError, NULL);
|
211
|
+
}
|
212
|
+
return self;
|
213
|
+
}
|
214
|
+
|
215
|
+
GetBN(self, bn);
|
216
|
+
switch (base) {
|
217
|
+
case 0:
|
218
|
+
if (!BN_mpi2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
|
219
|
+
ossl_raise(eBNError, NULL);
|
220
|
+
}
|
221
|
+
break;
|
222
|
+
case 2:
|
223
|
+
if (!BN_bin2bn((unsigned char *)StringValuePtr(str), RSTRING_LENINT(str), bn)) {
|
224
|
+
ossl_raise(eBNError, NULL);
|
225
|
+
}
|
226
|
+
break;
|
227
|
+
case 10:
|
228
|
+
if (!BN_dec2bn(&bn, StringValueCStr(str))) {
|
229
|
+
ossl_raise(eBNError, NULL);
|
230
|
+
}
|
231
|
+
break;
|
232
|
+
case 16:
|
233
|
+
if (!BN_hex2bn(&bn, StringValueCStr(str))) {
|
234
|
+
ossl_raise(eBNError, NULL);
|
235
|
+
}
|
236
|
+
break;
|
237
|
+
default:
|
238
|
+
ossl_raise(rb_eArgError, "invalid radix %d", base);
|
239
|
+
}
|
240
|
+
return self;
|
241
|
+
}
|
242
|
+
|
243
|
+
/*
|
244
|
+
* call-seq:
|
245
|
+
* bn.to_s => string
|
246
|
+
* bn.to_s(base) => string
|
247
|
+
*
|
248
|
+
* === Parameters
|
249
|
+
* * +base+ - integer
|
250
|
+
* Valid values:
|
251
|
+
* * 0 - MPI
|
252
|
+
* * 2 - binary
|
253
|
+
* * 10 - the default
|
254
|
+
* * 16 - hex
|
255
|
+
*/
|
256
|
+
static VALUE
|
257
|
+
ossl_bn_to_s(int argc, VALUE *argv, VALUE self)
|
258
|
+
{
|
259
|
+
BIGNUM *bn;
|
260
|
+
VALUE str, bs;
|
261
|
+
int base = 10, len;
|
262
|
+
char *buf;
|
263
|
+
|
264
|
+
if (rb_scan_args(argc, argv, "01", &bs) == 1) {
|
265
|
+
base = NUM2INT(bs);
|
266
|
+
}
|
267
|
+
GetBN(self, bn);
|
268
|
+
switch (base) {
|
269
|
+
case 0:
|
270
|
+
len = BN_bn2mpi(bn, NULL);
|
271
|
+
str = rb_str_new(0, len);
|
272
|
+
if (BN_bn2mpi(bn, (unsigned char *)RSTRING_PTR(str)) != len)
|
273
|
+
ossl_raise(eBNError, NULL);
|
274
|
+
break;
|
275
|
+
case 2:
|
276
|
+
len = BN_num_bytes(bn);
|
277
|
+
str = rb_str_new(0, len);
|
278
|
+
if (BN_bn2bin(bn, (unsigned char *)RSTRING_PTR(str)) != len)
|
279
|
+
ossl_raise(eBNError, NULL);
|
280
|
+
break;
|
281
|
+
case 10:
|
282
|
+
if (!(buf = BN_bn2dec(bn))) ossl_raise(eBNError, NULL);
|
283
|
+
str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
|
284
|
+
break;
|
285
|
+
case 16:
|
286
|
+
if (!(buf = BN_bn2hex(bn))) ossl_raise(eBNError, NULL);
|
287
|
+
str = ossl_buf2str(buf, rb_long2int(strlen(buf)));
|
288
|
+
break;
|
289
|
+
default:
|
290
|
+
ossl_raise(rb_eArgError, "invalid radix %d", base);
|
291
|
+
}
|
292
|
+
|
293
|
+
return str;
|
294
|
+
}
|
295
|
+
|
296
|
+
/*
|
297
|
+
* call-seq:
|
298
|
+
* bn.to_i => integer
|
299
|
+
*/
|
300
|
+
static VALUE
|
301
|
+
ossl_bn_to_i(VALUE self)
|
302
|
+
{
|
303
|
+
BIGNUM *bn;
|
304
|
+
char *txt;
|
305
|
+
VALUE num;
|
306
|
+
|
307
|
+
GetBN(self, bn);
|
308
|
+
|
309
|
+
if (!(txt = BN_bn2hex(bn))) {
|
310
|
+
ossl_raise(eBNError, NULL);
|
311
|
+
}
|
312
|
+
num = rb_cstr_to_inum(txt, 16, Qtrue);
|
313
|
+
OPENSSL_free(txt);
|
314
|
+
|
315
|
+
return num;
|
316
|
+
}
|
317
|
+
|
318
|
+
static VALUE
|
319
|
+
ossl_bn_to_bn(VALUE self)
|
320
|
+
{
|
321
|
+
return self;
|
322
|
+
}
|
323
|
+
|
324
|
+
static VALUE
|
325
|
+
ossl_bn_coerce(VALUE self, VALUE other)
|
326
|
+
{
|
327
|
+
switch(TYPE(other)) {
|
328
|
+
case T_STRING:
|
329
|
+
self = ossl_bn_to_s(0, NULL, self);
|
330
|
+
break;
|
331
|
+
case T_FIXNUM:
|
332
|
+
case T_BIGNUM:
|
333
|
+
self = ossl_bn_to_i(self);
|
334
|
+
break;
|
335
|
+
default:
|
336
|
+
if (!RTEST(rb_obj_is_kind_of(other, cBN))) {
|
337
|
+
ossl_raise(rb_eTypeError, "Don't know how to coerce");
|
338
|
+
}
|
339
|
+
}
|
340
|
+
return rb_assoc_new(other, self);
|
341
|
+
}
|
342
|
+
|
343
|
+
#define BIGNUM_BOOL1(func) \
|
344
|
+
static VALUE \
|
345
|
+
ossl_bn_##func(VALUE self) \
|
346
|
+
{ \
|
347
|
+
BIGNUM *bn; \
|
348
|
+
GetBN(self, bn); \
|
349
|
+
if (BN_##func(bn)) { \
|
350
|
+
return Qtrue; \
|
351
|
+
} \
|
352
|
+
return Qfalse; \
|
353
|
+
}
|
354
|
+
|
355
|
+
/*
|
356
|
+
* Document-method: OpenSSL::BN#zero?
|
357
|
+
* call-seq:
|
358
|
+
* bn.zero? => true | false
|
359
|
+
*/
|
360
|
+
BIGNUM_BOOL1(is_zero)
|
361
|
+
|
362
|
+
/*
|
363
|
+
* Document-method: OpenSSL::BN#one?
|
364
|
+
* call-seq:
|
365
|
+
* bn.one? => true | false
|
366
|
+
*/
|
367
|
+
BIGNUM_BOOL1(is_one)
|
368
|
+
|
369
|
+
/*
|
370
|
+
* Document-method: OpenSSL::BN#odd?
|
371
|
+
* call-seq:
|
372
|
+
* bn.odd? => true | false
|
373
|
+
*/
|
374
|
+
BIGNUM_BOOL1(is_odd)
|
375
|
+
|
376
|
+
#define BIGNUM_1c(func) \
|
377
|
+
static VALUE \
|
378
|
+
ossl_bn_##func(VALUE self) \
|
379
|
+
{ \
|
380
|
+
BIGNUM *bn, *result; \
|
381
|
+
VALUE obj; \
|
382
|
+
GetBN(self, bn); \
|
383
|
+
obj = NewBN(CLASS_OF(self)); \
|
384
|
+
if (!(result = BN_new())) { \
|
385
|
+
ossl_raise(eBNError, NULL); \
|
386
|
+
} \
|
387
|
+
if (!BN_##func(result, bn, ossl_bn_ctx)) { \
|
388
|
+
BN_free(result); \
|
389
|
+
ossl_raise(eBNError, NULL); \
|
390
|
+
} \
|
391
|
+
SetBN(obj, result); \
|
392
|
+
return obj; \
|
393
|
+
}
|
394
|
+
|
395
|
+
/*
|
396
|
+
* Document-method: OpenSSL::BN#sqr
|
397
|
+
* call-seq:
|
398
|
+
* bn.sqr => aBN
|
399
|
+
*/
|
400
|
+
BIGNUM_1c(sqr)
|
401
|
+
|
402
|
+
#define BIGNUM_2(func) \
|
403
|
+
static VALUE \
|
404
|
+
ossl_bn_##func(VALUE self, VALUE other) \
|
405
|
+
{ \
|
406
|
+
BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
|
407
|
+
VALUE obj; \
|
408
|
+
GetBN(self, bn1); \
|
409
|
+
obj = NewBN(CLASS_OF(self)); \
|
410
|
+
if (!(result = BN_new())) { \
|
411
|
+
ossl_raise(eBNError, NULL); \
|
412
|
+
} \
|
413
|
+
if (!BN_##func(result, bn1, bn2)) { \
|
414
|
+
BN_free(result); \
|
415
|
+
ossl_raise(eBNError, NULL); \
|
416
|
+
} \
|
417
|
+
SetBN(obj, result); \
|
418
|
+
return obj; \
|
419
|
+
}
|
420
|
+
|
421
|
+
/*
|
422
|
+
* Document-method: OpenSSL::BN#+
|
423
|
+
* call-seq:
|
424
|
+
* bn + bn2 => aBN
|
425
|
+
*/
|
426
|
+
BIGNUM_2(add)
|
427
|
+
|
428
|
+
/*
|
429
|
+
* Document-method: OpenSSL::BN#-
|
430
|
+
* call-seq:
|
431
|
+
* bn - bn2 => aBN
|
432
|
+
*/
|
433
|
+
BIGNUM_2(sub)
|
434
|
+
|
435
|
+
#define BIGNUM_2c(func) \
|
436
|
+
static VALUE \
|
437
|
+
ossl_bn_##func(VALUE self, VALUE other) \
|
438
|
+
{ \
|
439
|
+
BIGNUM *bn1, *bn2 = GetBNPtr(other), *result; \
|
440
|
+
VALUE obj; \
|
441
|
+
GetBN(self, bn1); \
|
442
|
+
obj = NewBN(CLASS_OF(self)); \
|
443
|
+
if (!(result = BN_new())) { \
|
444
|
+
ossl_raise(eBNError, NULL); \
|
445
|
+
} \
|
446
|
+
if (!BN_##func(result, bn1, bn2, ossl_bn_ctx)) { \
|
447
|
+
BN_free(result); \
|
448
|
+
ossl_raise(eBNError, NULL); \
|
449
|
+
} \
|
450
|
+
SetBN(obj, result); \
|
451
|
+
return obj; \
|
452
|
+
}
|
453
|
+
|
454
|
+
/*
|
455
|
+
* Document-method: OpenSSL::BN#*
|
456
|
+
* call-seq:
|
457
|
+
* bn * bn2 => aBN
|
458
|
+
*/
|
459
|
+
BIGNUM_2c(mul)
|
460
|
+
|
461
|
+
/*
|
462
|
+
* Document-method: OpenSSL::BN#%
|
463
|
+
* call-seq:
|
464
|
+
* bn % bn2 => aBN
|
465
|
+
*/
|
466
|
+
BIGNUM_2c(mod)
|
467
|
+
|
468
|
+
/*
|
469
|
+
* Document-method: OpenSSL::BN#**
|
470
|
+
* call-seq:
|
471
|
+
* bn ** bn2 => aBN
|
472
|
+
*/
|
473
|
+
BIGNUM_2c(exp)
|
474
|
+
|
475
|
+
/*
|
476
|
+
* Document-method: OpenSSL::BN#gcd
|
477
|
+
* call-seq:
|
478
|
+
* bn.gcd(bn2) => aBN
|
479
|
+
*/
|
480
|
+
BIGNUM_2c(gcd)
|
481
|
+
|
482
|
+
/*
|
483
|
+
* Document-method: OpenSSL::BN#mod_sqr
|
484
|
+
* call-seq:
|
485
|
+
* bn.mod_sqr(bn2) => aBN
|
486
|
+
*/
|
487
|
+
BIGNUM_2c(mod_sqr)
|
488
|
+
|
489
|
+
/*
|
490
|
+
* Document-method: OpenSSL::BN#mod_inverse
|
491
|
+
* call-seq:
|
492
|
+
* bn.mod_inverse(bn2) => aBN
|
493
|
+
*/
|
494
|
+
BIGNUM_2c(mod_inverse)
|
495
|
+
|
496
|
+
/*
|
497
|
+
* Document-method: OpenSSL::BN#/
|
498
|
+
* call-seq:
|
499
|
+
* bn1 / bn2 => [result, remainder]
|
500
|
+
*
|
501
|
+
* Division of OpenSSL::BN instances
|
502
|
+
*/
|
503
|
+
static VALUE
|
504
|
+
ossl_bn_div(VALUE self, VALUE other)
|
505
|
+
{
|
506
|
+
BIGNUM *bn1, *bn2 = GetBNPtr(other), *r1, *r2;
|
507
|
+
VALUE obj1, obj2;
|
508
|
+
|
509
|
+
GetBN(self, bn1);
|
510
|
+
|
511
|
+
obj1 = NewBN(CLASS_OF(self));
|
512
|
+
obj2 = NewBN(CLASS_OF(self));
|
513
|
+
if (!(r1 = BN_new())) {
|
514
|
+
ossl_raise(eBNError, NULL);
|
515
|
+
}
|
516
|
+
if (!(r2 = BN_new())) {
|
517
|
+
BN_free(r1);
|
518
|
+
ossl_raise(eBNError, NULL);
|
519
|
+
}
|
520
|
+
if (!BN_div(r1, r2, bn1, bn2, ossl_bn_ctx)) {
|
521
|
+
BN_free(r1);
|
522
|
+
BN_free(r2);
|
523
|
+
ossl_raise(eBNError, NULL);
|
524
|
+
}
|
525
|
+
SetBN(obj1, r1);
|
526
|
+
SetBN(obj2, r2);
|
527
|
+
|
528
|
+
return rb_ary_new3(2, obj1, obj2);
|
529
|
+
}
|
530
|
+
|
531
|
+
#define BIGNUM_3c(func) \
|
532
|
+
static VALUE \
|
533
|
+
ossl_bn_##func(VALUE self, VALUE other1, VALUE other2) \
|
534
|
+
{ \
|
535
|
+
BIGNUM *bn1, *bn2 = GetBNPtr(other1); \
|
536
|
+
BIGNUM *bn3 = GetBNPtr(other2), *result; \
|
537
|
+
VALUE obj; \
|
538
|
+
GetBN(self, bn1); \
|
539
|
+
obj = NewBN(CLASS_OF(self)); \
|
540
|
+
if (!(result = BN_new())) { \
|
541
|
+
ossl_raise(eBNError, NULL); \
|
542
|
+
} \
|
543
|
+
if (!BN_##func(result, bn1, bn2, bn3, ossl_bn_ctx)) { \
|
544
|
+
BN_free(result); \
|
545
|
+
ossl_raise(eBNError, NULL); \
|
546
|
+
} \
|
547
|
+
SetBN(obj, result); \
|
548
|
+
return obj; \
|
549
|
+
}
|
550
|
+
|
551
|
+
/*
|
552
|
+
* Document-method: OpenSSL::BN#mod_add
|
553
|
+
* call-seq:
|
554
|
+
* bn.mod_add(bn1, bn2) -> aBN
|
555
|
+
*/
|
556
|
+
BIGNUM_3c(mod_add)
|
557
|
+
|
558
|
+
/*
|
559
|
+
* Document-method: OpenSSL::BN#mod_sub
|
560
|
+
* call-seq:
|
561
|
+
* bn.mod_sub(bn1, bn2) -> aBN
|
562
|
+
*/
|
563
|
+
BIGNUM_3c(mod_sub)
|
564
|
+
|
565
|
+
/*
|
566
|
+
* Document-method: OpenSSL::BN#mod_mul
|
567
|
+
* call-seq:
|
568
|
+
* bn.mod_mul(bn1, bn2) -> aBN
|
569
|
+
*/
|
570
|
+
BIGNUM_3c(mod_mul)
|
571
|
+
|
572
|
+
/*
|
573
|
+
* Document-method: OpenSSL::BN#mod_exp
|
574
|
+
* call-seq:
|
575
|
+
* bn.mod_exp(bn1, bn2) -> aBN
|
576
|
+
*/
|
577
|
+
BIGNUM_3c(mod_exp)
|
578
|
+
|
579
|
+
#define BIGNUM_BIT(func) \
|
580
|
+
static VALUE \
|
581
|
+
ossl_bn_##func(VALUE self, VALUE bit) \
|
582
|
+
{ \
|
583
|
+
BIGNUM *bn; \
|
584
|
+
GetBN(self, bn); \
|
585
|
+
if (!BN_##func(bn, NUM2INT(bit))) { \
|
586
|
+
ossl_raise(eBNError, NULL); \
|
587
|
+
} \
|
588
|
+
return self; \
|
589
|
+
}
|
590
|
+
|
591
|
+
/*
|
592
|
+
* Document-method: OpenSSL::BN#set_bit!
|
593
|
+
* call-seq:
|
594
|
+
* bn.set_bit!(bit) -> self
|
595
|
+
*/
|
596
|
+
BIGNUM_BIT(set_bit)
|
597
|
+
|
598
|
+
/*
|
599
|
+
* Document-method: OpenSSL::BN#clear_bit!
|
600
|
+
* call-seq:
|
601
|
+
* bn.clear_bit!(bit) -> self
|
602
|
+
*/
|
603
|
+
BIGNUM_BIT(clear_bit)
|
604
|
+
|
605
|
+
/*
|
606
|
+
* Document-method: OpenSSL::BN#mask_bit!
|
607
|
+
* call-seq:
|
608
|
+
* bn.mask_bit!(bit) -> self
|
609
|
+
*/
|
610
|
+
BIGNUM_BIT(mask_bits)
|
611
|
+
|
612
|
+
/* Document-method: OpenSSL::BN#bit_set?
|
613
|
+
* call-seq:
|
614
|
+
* bn.bit_set?(bit) => true | false
|
615
|
+
*
|
616
|
+
* Returns boolean of whether +bit+ is set.
|
617
|
+
* Bitwise operations for openssl BIGNUMs.
|
618
|
+
*/
|
619
|
+
static VALUE
|
620
|
+
ossl_bn_is_bit_set(VALUE self, VALUE bit)
|
621
|
+
{
|
622
|
+
int b;
|
623
|
+
BIGNUM *bn;
|
624
|
+
|
625
|
+
b = NUM2INT(bit);
|
626
|
+
GetBN(self, bn);
|
627
|
+
if (BN_is_bit_set(bn, b)) {
|
628
|
+
return Qtrue;
|
629
|
+
}
|
630
|
+
return Qfalse;
|
631
|
+
}
|
632
|
+
|
633
|
+
#define BIGNUM_SHIFT(func) \
|
634
|
+
static VALUE \
|
635
|
+
ossl_bn_##func(VALUE self, VALUE bits) \
|
636
|
+
{ \
|
637
|
+
BIGNUM *bn, *result; \
|
638
|
+
int b; \
|
639
|
+
VALUE obj; \
|
640
|
+
b = NUM2INT(bits); \
|
641
|
+
GetBN(self, bn); \
|
642
|
+
obj = NewBN(CLASS_OF(self)); \
|
643
|
+
if (!(result = BN_new())) { \
|
644
|
+
ossl_raise(eBNError, NULL); \
|
645
|
+
} \
|
646
|
+
if (!BN_##func(result, bn, b)) { \
|
647
|
+
BN_free(result); \
|
648
|
+
ossl_raise(eBNError, NULL); \
|
649
|
+
} \
|
650
|
+
SetBN(obj, result); \
|
651
|
+
return obj; \
|
652
|
+
}
|
653
|
+
|
654
|
+
/*
|
655
|
+
* Document-method: OpenSSL::BN#<<
|
656
|
+
* call-seq:
|
657
|
+
* bn << bits -> aBN
|
658
|
+
*/
|
659
|
+
BIGNUM_SHIFT(lshift)
|
660
|
+
|
661
|
+
/*
|
662
|
+
* Document-method: OpenSSL::BN#>>
|
663
|
+
* call-seq:
|
664
|
+
* bn >> bits -> aBN
|
665
|
+
*/
|
666
|
+
BIGNUM_SHIFT(rshift)
|
667
|
+
|
668
|
+
#define BIGNUM_SELF_SHIFT(func) \
|
669
|
+
static VALUE \
|
670
|
+
ossl_bn_self_##func(VALUE self, VALUE bits) \
|
671
|
+
{ \
|
672
|
+
BIGNUM *bn; \
|
673
|
+
int b; \
|
674
|
+
b = NUM2INT(bits); \
|
675
|
+
GetBN(self, bn); \
|
676
|
+
if (!BN_##func(bn, bn, b)) \
|
677
|
+
ossl_raise(eBNError, NULL); \
|
678
|
+
return self; \
|
679
|
+
}
|
680
|
+
|
681
|
+
/*
|
682
|
+
* Document-method: OpenSSL::BN#lshift!
|
683
|
+
* call-seq:
|
684
|
+
* bn.lshift!(bits) -> self
|
685
|
+
*/
|
686
|
+
BIGNUM_SELF_SHIFT(lshift)
|
687
|
+
|
688
|
+
/*
|
689
|
+
* Document-method: OpenSSL::BN#rshift!
|
690
|
+
* call-seq:
|
691
|
+
* bn.rshift!(bits) -> self
|
692
|
+
*/
|
693
|
+
BIGNUM_SELF_SHIFT(rshift)
|
694
|
+
|
695
|
+
#define BIGNUM_RAND(func) \
|
696
|
+
static VALUE \
|
697
|
+
ossl_bn_s_##func(int argc, VALUE *argv, VALUE klass) \
|
698
|
+
{ \
|
699
|
+
BIGNUM *result; \
|
700
|
+
int bottom = 0, top = 0, b; \
|
701
|
+
VALUE bits, fill, odd, obj; \
|
702
|
+
\
|
703
|
+
switch (rb_scan_args(argc, argv, "12", &bits, &fill, &odd)) { \
|
704
|
+
case 3: \
|
705
|
+
bottom = (odd == Qtrue) ? 1 : 0; \
|
706
|
+
/* FALLTHROUGH */ \
|
707
|
+
case 2: \
|
708
|
+
top = NUM2INT(fill); \
|
709
|
+
} \
|
710
|
+
b = NUM2INT(bits); \
|
711
|
+
obj = NewBN(klass); \
|
712
|
+
if (!(result = BN_new())) { \
|
713
|
+
ossl_raise(eBNError, NULL); \
|
714
|
+
} \
|
715
|
+
if (!BN_##func(result, b, top, bottom)) { \
|
716
|
+
BN_free(result); \
|
717
|
+
ossl_raise(eBNError, NULL); \
|
718
|
+
} \
|
719
|
+
SetBN(obj, result); \
|
720
|
+
return obj; \
|
721
|
+
}
|
722
|
+
|
723
|
+
/*
|
724
|
+
* Document-method: OpenSSL::BN.rand
|
725
|
+
* BN.rand(bits [, fill [, odd]]) -> aBN
|
726
|
+
*/
|
727
|
+
BIGNUM_RAND(rand)
|
728
|
+
|
729
|
+
/*
|
730
|
+
* Document-method: OpenSSL::BN.pseudo_rand
|
731
|
+
* BN.pseudo_rand(bits [, fill [, odd]]) -> aBN
|
732
|
+
*/
|
733
|
+
BIGNUM_RAND(pseudo_rand)
|
734
|
+
|
735
|
+
#define BIGNUM_RAND_RANGE(func) \
|
736
|
+
static VALUE \
|
737
|
+
ossl_bn_s_##func##_range(VALUE klass, VALUE range) \
|
738
|
+
{ \
|
739
|
+
BIGNUM *bn = GetBNPtr(range), *result; \
|
740
|
+
VALUE obj = NewBN(klass); \
|
741
|
+
if (!(result = BN_new())) { \
|
742
|
+
ossl_raise(eBNError, NULL); \
|
743
|
+
} \
|
744
|
+
if (!BN_##func##_range(result, bn)) { \
|
745
|
+
BN_free(result); \
|
746
|
+
ossl_raise(eBNError, NULL); \
|
747
|
+
} \
|
748
|
+
SetBN(obj, result); \
|
749
|
+
return obj; \
|
750
|
+
}
|
751
|
+
|
752
|
+
/*
|
753
|
+
* Document-method: OpenSSL::BN.rand_range
|
754
|
+
* call-seq:
|
755
|
+
* BN.rand_range(range) -> aBN
|
756
|
+
*
|
757
|
+
*/
|
758
|
+
BIGNUM_RAND_RANGE(rand)
|
759
|
+
|
760
|
+
/*
|
761
|
+
* Document-method: OpenSSL::BN.pseudo_rand_range
|
762
|
+
* call-seq:
|
763
|
+
* BN.pseudo_rand_range(range) -> aBN
|
764
|
+
*
|
765
|
+
*/
|
766
|
+
BIGNUM_RAND_RANGE(pseudo_rand)
|
767
|
+
|
768
|
+
/*
|
769
|
+
* call-seq:
|
770
|
+
* BN.generate_prime(bits, [, safe [, add [, rem]]]) => bn
|
771
|
+
*
|
772
|
+
* Generates a random prime number of bit length +bits+. If +safe+ is true,
|
773
|
+
* generates a safe prime. If +add+ is specified, generates a prime that
|
774
|
+
* fulfills condition <tt>p % add = rem</tt>.
|
775
|
+
*
|
776
|
+
* === Parameters
|
777
|
+
* * +bits+ - integer
|
778
|
+
* * +safe+ - boolean
|
779
|
+
* * +add+ - BN
|
780
|
+
* * +rem+ - BN
|
781
|
+
*/
|
782
|
+
static VALUE
|
783
|
+
ossl_bn_s_generate_prime(int argc, VALUE *argv, VALUE klass)
|
784
|
+
{
|
785
|
+
BIGNUM *add = NULL, *rem = NULL, *result;
|
786
|
+
int safe = 1, num;
|
787
|
+
VALUE vnum, vsafe, vadd, vrem, obj;
|
788
|
+
|
789
|
+
rb_scan_args(argc, argv, "13", &vnum, &vsafe, &vadd, &vrem);
|
790
|
+
|
791
|
+
num = NUM2INT(vnum);
|
792
|
+
|
793
|
+
if (vsafe == Qfalse) {
|
794
|
+
safe = 0;
|
795
|
+
}
|
796
|
+
if (!NIL_P(vadd)) {
|
797
|
+
add = GetBNPtr(vadd);
|
798
|
+
rem = NIL_P(vrem) ? NULL : GetBNPtr(vrem);
|
799
|
+
}
|
800
|
+
obj = NewBN(klass);
|
801
|
+
if (!(result = BN_new())) {
|
802
|
+
ossl_raise(eBNError, NULL);
|
803
|
+
}
|
804
|
+
if (!BN_generate_prime_ex(result, num, safe, add, rem, NULL)) {
|
805
|
+
BN_free(result);
|
806
|
+
ossl_raise(eBNError, NULL);
|
807
|
+
}
|
808
|
+
SetBN(obj, result);
|
809
|
+
|
810
|
+
return obj;
|
811
|
+
}
|
812
|
+
|
813
|
+
#define BIGNUM_NUM(func) \
|
814
|
+
static VALUE \
|
815
|
+
ossl_bn_##func(VALUE self) \
|
816
|
+
{ \
|
817
|
+
BIGNUM *bn; \
|
818
|
+
GetBN(self, bn); \
|
819
|
+
return INT2NUM(BN_##func(bn)); \
|
820
|
+
}
|
821
|
+
|
822
|
+
/*
|
823
|
+
* Document-method: OpenSSL::BN#num_bytes
|
824
|
+
* call-seq:
|
825
|
+
* bn.num_bytes => integer
|
826
|
+
*/
|
827
|
+
BIGNUM_NUM(num_bytes)
|
828
|
+
|
829
|
+
/*
|
830
|
+
* Document-method: OpenSSL::BN#num_bits
|
831
|
+
* call-seq:
|
832
|
+
* bn.num_bits => integer
|
833
|
+
*/
|
834
|
+
BIGNUM_NUM(num_bits)
|
835
|
+
|
836
|
+
static VALUE
|
837
|
+
ossl_bn_copy(VALUE self, VALUE other)
|
838
|
+
{
|
839
|
+
BIGNUM *bn1, *bn2;
|
840
|
+
|
841
|
+
rb_check_frozen(self);
|
842
|
+
|
843
|
+
if (self == other) return self;
|
844
|
+
|
845
|
+
GetBN(self, bn1);
|
846
|
+
bn2 = GetBNPtr(other);
|
847
|
+
|
848
|
+
if (!BN_copy(bn1, bn2)) {
|
849
|
+
ossl_raise(eBNError, NULL);
|
850
|
+
}
|
851
|
+
return self;
|
852
|
+
}
|
853
|
+
|
854
|
+
#define BIGNUM_CMP(func) \
|
855
|
+
static VALUE \
|
856
|
+
ossl_bn_##func(VALUE self, VALUE other) \
|
857
|
+
{ \
|
858
|
+
BIGNUM *bn1, *bn2 = GetBNPtr(other); \
|
859
|
+
GetBN(self, bn1); \
|
860
|
+
return INT2NUM(BN_##func(bn1, bn2)); \
|
861
|
+
}
|
862
|
+
|
863
|
+
/*
|
864
|
+
* Document-method: OpenSSL::BN#cmp
|
865
|
+
* call-seq:
|
866
|
+
* bn.cmp(bn2) => integer
|
867
|
+
*/
|
868
|
+
/*
|
869
|
+
* Document-method: OpenSSL::BN#<=>
|
870
|
+
* call-seq:
|
871
|
+
* bn <=> bn2 => integer
|
872
|
+
*/
|
873
|
+
BIGNUM_CMP(cmp)
|
874
|
+
|
875
|
+
/*
|
876
|
+
* Document-method: OpenSSL::BN#ucmp
|
877
|
+
* call-seq:
|
878
|
+
* bn.ucmp(bn2) => integer
|
879
|
+
*/
|
880
|
+
BIGNUM_CMP(ucmp)
|
881
|
+
|
882
|
+
/*
|
883
|
+
* call-seq:
|
884
|
+
* bn == obj => true or false
|
885
|
+
*
|
886
|
+
* Returns +true+ only if +obj+ has the same value as +bn+. Contrast this
|
887
|
+
* with OpenSSL::BN#eql?, which requires obj to be OpenSSL::BN.
|
888
|
+
*/
|
889
|
+
static VALUE
|
890
|
+
ossl_bn_eq(VALUE self, VALUE other)
|
891
|
+
{
|
892
|
+
BIGNUM *bn1, *bn2;
|
893
|
+
|
894
|
+
GetBN(self, bn1);
|
895
|
+
/* BNPtr may raise, so we can't use here */
|
896
|
+
bn2 = try_convert_to_bnptr(other);
|
897
|
+
|
898
|
+
if (bn2 && !BN_cmp(bn1, bn2)) {
|
899
|
+
return Qtrue;
|
900
|
+
}
|
901
|
+
return Qfalse;
|
902
|
+
}
|
903
|
+
|
904
|
+
/*
|
905
|
+
* call-seq:
|
906
|
+
* bn.eql?(obj) => true or false
|
907
|
+
*
|
908
|
+
* Returns <code>true</code> only if <i>obj</i> is a
|
909
|
+
* <code>OpenSSL::BN</code> with the same value as <i>big</i>. Contrast this
|
910
|
+
* with OpenSSL::BN#==, which performs type conversions.
|
911
|
+
*/
|
912
|
+
static VALUE
|
913
|
+
ossl_bn_eql(VALUE self, VALUE other)
|
914
|
+
{
|
915
|
+
BIGNUM *bn1, *bn2;
|
916
|
+
|
917
|
+
if (!rb_obj_is_kind_of(other, cBN))
|
918
|
+
return Qfalse;
|
919
|
+
GetBN(self, bn1);
|
920
|
+
GetBN(other, bn2);
|
921
|
+
|
922
|
+
return BN_cmp(bn1, bn2) ? Qfalse : Qtrue;
|
923
|
+
}
|
924
|
+
|
925
|
+
/*
|
926
|
+
* call-seq:
|
927
|
+
* bn.hash => Integer
|
928
|
+
*
|
929
|
+
* Returns a hash code for this object.
|
930
|
+
*
|
931
|
+
* See also Object#hash.
|
932
|
+
*/
|
933
|
+
static VALUE
|
934
|
+
ossl_bn_hash(VALUE self)
|
935
|
+
{
|
936
|
+
BIGNUM *bn;
|
937
|
+
VALUE hash;
|
938
|
+
unsigned char *buf;
|
939
|
+
int len;
|
940
|
+
|
941
|
+
GetBN(self, bn);
|
942
|
+
len = BN_num_bytes(bn);
|
943
|
+
buf = xmalloc(len);
|
944
|
+
if (BN_bn2bin(bn, buf) != len) {
|
945
|
+
xfree(buf);
|
946
|
+
ossl_raise(eBNError, NULL);
|
947
|
+
}
|
948
|
+
|
949
|
+
hash = INT2FIX(rb_memhash(buf, len));
|
950
|
+
xfree(buf);
|
951
|
+
|
952
|
+
return hash;
|
953
|
+
}
|
954
|
+
|
955
|
+
/*
|
956
|
+
* call-seq:
|
957
|
+
* bn.prime? => true | false
|
958
|
+
* bn.prime?(checks) => true | false
|
959
|
+
*
|
960
|
+
* Performs a Miller-Rabin probabilistic primality test with +checks+
|
961
|
+
* iterations. If +nchecks+ is not specified, a number of iterations is used
|
962
|
+
* that yields a false positive rate of at most 2^-80 for random input.
|
963
|
+
*
|
964
|
+
* === Parameters
|
965
|
+
* * +checks+ - integer
|
966
|
+
*/
|
967
|
+
static VALUE
|
968
|
+
ossl_bn_is_prime(int argc, VALUE *argv, VALUE self)
|
969
|
+
{
|
970
|
+
BIGNUM *bn;
|
971
|
+
VALUE vchecks;
|
972
|
+
int checks = BN_prime_checks;
|
973
|
+
|
974
|
+
if (rb_scan_args(argc, argv, "01", &vchecks) == 1) {
|
975
|
+
checks = NUM2INT(vchecks);
|
976
|
+
}
|
977
|
+
GetBN(self, bn);
|
978
|
+
switch (BN_is_prime_ex(bn, checks, ossl_bn_ctx, NULL)) {
|
979
|
+
case 1:
|
980
|
+
return Qtrue;
|
981
|
+
case 0:
|
982
|
+
return Qfalse;
|
983
|
+
default:
|
984
|
+
ossl_raise(eBNError, NULL);
|
985
|
+
}
|
986
|
+
/* not reachable */
|
987
|
+
return Qnil;
|
988
|
+
}
|
989
|
+
|
990
|
+
/*
|
991
|
+
* call-seq:
|
992
|
+
* bn.prime_fasttest? => true | false
|
993
|
+
* bn.prime_fasttest?(checks) => true | false
|
994
|
+
* bn.prime_fasttest?(checks, trial_div) => true | false
|
995
|
+
*
|
996
|
+
* Performs a Miller-Rabin primality test. This is same as #prime? except this
|
997
|
+
* first attempts trial divisions with some small primes.
|
998
|
+
*
|
999
|
+
* === Parameters
|
1000
|
+
* * +checks+ - integer
|
1001
|
+
* * +trial_div+ - boolean
|
1002
|
+
*/
|
1003
|
+
static VALUE
|
1004
|
+
ossl_bn_is_prime_fasttest(int argc, VALUE *argv, VALUE self)
|
1005
|
+
{
|
1006
|
+
BIGNUM *bn;
|
1007
|
+
VALUE vchecks, vtrivdiv;
|
1008
|
+
int checks = BN_prime_checks, do_trial_division = 1;
|
1009
|
+
|
1010
|
+
rb_scan_args(argc, argv, "02", &vchecks, &vtrivdiv);
|
1011
|
+
|
1012
|
+
if (!NIL_P(vchecks)) {
|
1013
|
+
checks = NUM2INT(vchecks);
|
1014
|
+
}
|
1015
|
+
GetBN(self, bn);
|
1016
|
+
/* handle true/false */
|
1017
|
+
if (vtrivdiv == Qfalse) {
|
1018
|
+
do_trial_division = 0;
|
1019
|
+
}
|
1020
|
+
switch (BN_is_prime_fasttest_ex(bn, checks, ossl_bn_ctx, do_trial_division, NULL)) {
|
1021
|
+
case 1:
|
1022
|
+
return Qtrue;
|
1023
|
+
case 0:
|
1024
|
+
return Qfalse;
|
1025
|
+
default:
|
1026
|
+
ossl_raise(eBNError, NULL);
|
1027
|
+
}
|
1028
|
+
/* not reachable */
|
1029
|
+
return Qnil;
|
1030
|
+
}
|
1031
|
+
|
1032
|
+
/*
|
1033
|
+
* INIT
|
1034
|
+
* (NOTE: ordering of methods is the same as in 'man bn')
|
1035
|
+
*/
|
1036
|
+
void
|
1037
|
+
Init_ossl_bn(void)
|
1038
|
+
{
|
1039
|
+
#if 0
|
1040
|
+
mOSSL = rb_define_module("OpenSSL");
|
1041
|
+
eOSSLError = rb_define_class_under(mOSSL, "OpenSSLError", rb_eStandardError);
|
1042
|
+
#endif
|
1043
|
+
|
1044
|
+
if (!(ossl_bn_ctx = BN_CTX_new())) {
|
1045
|
+
ossl_raise(rb_eRuntimeError, "Cannot init BN_CTX");
|
1046
|
+
}
|
1047
|
+
|
1048
|
+
eBNError = rb_define_class_under(mOSSL, "BNError", eOSSLError);
|
1049
|
+
|
1050
|
+
cBN = rb_define_class_under(mOSSL, "BN", rb_cObject);
|
1051
|
+
|
1052
|
+
rb_define_alloc_func(cBN, ossl_bn_alloc);
|
1053
|
+
rb_define_method(cBN, "initialize", ossl_bn_initialize, -1);
|
1054
|
+
|
1055
|
+
rb_define_copy_func(cBN, ossl_bn_copy);
|
1056
|
+
rb_define_method(cBN, "copy", ossl_bn_copy, 1);
|
1057
|
+
|
1058
|
+
/* swap (=coerce?) */
|
1059
|
+
|
1060
|
+
rb_define_method(cBN, "num_bytes", ossl_bn_num_bytes, 0);
|
1061
|
+
rb_define_method(cBN, "num_bits", ossl_bn_num_bits, 0);
|
1062
|
+
/* num_bits_word */
|
1063
|
+
|
1064
|
+
rb_define_method(cBN, "+", ossl_bn_add, 1);
|
1065
|
+
rb_define_method(cBN, "-", ossl_bn_sub, 1);
|
1066
|
+
rb_define_method(cBN, "*", ossl_bn_mul, 1);
|
1067
|
+
rb_define_method(cBN, "sqr", ossl_bn_sqr, 0);
|
1068
|
+
rb_define_method(cBN, "/", ossl_bn_div, 1);
|
1069
|
+
rb_define_method(cBN, "%", ossl_bn_mod, 1);
|
1070
|
+
/* nnmod */
|
1071
|
+
|
1072
|
+
rb_define_method(cBN, "mod_add", ossl_bn_mod_add, 2);
|
1073
|
+
rb_define_method(cBN, "mod_sub", ossl_bn_mod_sub, 2);
|
1074
|
+
rb_define_method(cBN, "mod_mul", ossl_bn_mod_mul, 2);
|
1075
|
+
rb_define_method(cBN, "mod_sqr", ossl_bn_mod_sqr, 1);
|
1076
|
+
rb_define_method(cBN, "**", ossl_bn_exp, 1);
|
1077
|
+
rb_define_method(cBN, "mod_exp", ossl_bn_mod_exp, 2);
|
1078
|
+
rb_define_method(cBN, "gcd", ossl_bn_gcd, 1);
|
1079
|
+
|
1080
|
+
/* add_word
|
1081
|
+
* sub_word
|
1082
|
+
* mul_word
|
1083
|
+
* div_word
|
1084
|
+
* mod_word */
|
1085
|
+
|
1086
|
+
rb_define_method(cBN, "cmp", ossl_bn_cmp, 1);
|
1087
|
+
rb_define_alias(cBN, "<=>", "cmp");
|
1088
|
+
rb_define_method(cBN, "ucmp", ossl_bn_ucmp, 1);
|
1089
|
+
rb_define_method(cBN, "eql?", ossl_bn_eql, 1);
|
1090
|
+
rb_define_method(cBN, "hash", ossl_bn_hash, 0);
|
1091
|
+
rb_define_method(cBN, "==", ossl_bn_eq, 1);
|
1092
|
+
rb_define_alias(cBN, "===", "==");
|
1093
|
+
rb_define_method(cBN, "zero?", ossl_bn_is_zero, 0);
|
1094
|
+
rb_define_method(cBN, "one?", ossl_bn_is_one, 0);
|
1095
|
+
/* is_word */
|
1096
|
+
rb_define_method(cBN, "odd?", ossl_bn_is_odd, 0);
|
1097
|
+
|
1098
|
+
/* zero
|
1099
|
+
* one
|
1100
|
+
* value_one - DON'T IMPL.
|
1101
|
+
* set_word
|
1102
|
+
* get_word */
|
1103
|
+
|
1104
|
+
rb_define_singleton_method(cBN, "rand", ossl_bn_s_rand, -1);
|
1105
|
+
rb_define_singleton_method(cBN, "pseudo_rand", ossl_bn_s_pseudo_rand, -1);
|
1106
|
+
rb_define_singleton_method(cBN, "rand_range", ossl_bn_s_rand_range, 1);
|
1107
|
+
rb_define_singleton_method(cBN, "pseudo_rand_range", ossl_bn_s_pseudo_rand_range, 1);
|
1108
|
+
|
1109
|
+
rb_define_singleton_method(cBN, "generate_prime", ossl_bn_s_generate_prime, -1);
|
1110
|
+
rb_define_method(cBN, "prime?", ossl_bn_is_prime, -1);
|
1111
|
+
rb_define_method(cBN, "prime_fasttest?", ossl_bn_is_prime_fasttest, -1);
|
1112
|
+
|
1113
|
+
rb_define_method(cBN, "set_bit!", ossl_bn_set_bit, 1);
|
1114
|
+
rb_define_method(cBN, "clear_bit!", ossl_bn_clear_bit, 1);
|
1115
|
+
rb_define_method(cBN, "bit_set?", ossl_bn_is_bit_set, 1);
|
1116
|
+
rb_define_method(cBN, "mask_bits!", ossl_bn_mask_bits, 1);
|
1117
|
+
rb_define_method(cBN, "<<", ossl_bn_lshift, 1);
|
1118
|
+
rb_define_method(cBN, ">>", ossl_bn_rshift, 1);
|
1119
|
+
rb_define_method(cBN, "lshift!", ossl_bn_self_lshift, 1);
|
1120
|
+
rb_define_method(cBN, "rshift!", ossl_bn_self_rshift, 1);
|
1121
|
+
/* lshift1 - DON'T IMPL. */
|
1122
|
+
/* rshift1 - DON'T IMPL. */
|
1123
|
+
|
1124
|
+
/*
|
1125
|
+
* bn2bin
|
1126
|
+
* bin2bn
|
1127
|
+
* bn2hex
|
1128
|
+
* bn2dec
|
1129
|
+
* hex2bn
|
1130
|
+
* dec2bn - all these are implemented in ossl_bn_initialize, and ossl_bn_to_s
|
1131
|
+
* print - NOT IMPL.
|
1132
|
+
* print_fp - NOT IMPL.
|
1133
|
+
* bn2mpi
|
1134
|
+
* mpi2bn
|
1135
|
+
*/
|
1136
|
+
rb_define_method(cBN, "to_s", ossl_bn_to_s, -1);
|
1137
|
+
rb_define_method(cBN, "to_i", ossl_bn_to_i, 0);
|
1138
|
+
rb_define_alias(cBN, "to_int", "to_i");
|
1139
|
+
rb_define_method(cBN, "to_bn", ossl_bn_to_bn, 0);
|
1140
|
+
rb_define_method(cBN, "coerce", ossl_bn_coerce, 1);
|
1141
|
+
|
1142
|
+
/*
|
1143
|
+
* TODO:
|
1144
|
+
* But how to: from_bin, from_mpi? PACK?
|
1145
|
+
* to_bin
|
1146
|
+
* to_mpi
|
1147
|
+
*/
|
1148
|
+
|
1149
|
+
rb_define_method(cBN, "mod_inverse", ossl_bn_mod_inverse, 1);
|
1150
|
+
|
1151
|
+
/* RECiProcal
|
1152
|
+
* MONTgomery */
|
1153
|
+
}
|