aboutsummaryrefslogtreecommitdiffstats
path: root/ossl_pkey.c
blob: b93ef53d4a464af075696c74eb90fa184c6cc373 (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
/*
 * $Id$
 * 'OpenSSL for Ruby' project
 * Copyright (C) 2001-2002  Michal Rokos <m.rokos@sh.cvut.cz>
 * All rights reserved.
 */
/*
 * This program is licenced under the same licence as Ruby.
 * (See the file 'LICENCE'.)
 */
#include "ossl.h"
#include "ossl_pkey.h"

#define GetPKey(obj, pkeyp) do {\
	Data_Get_Struct(obj, ossl_pkey, pkeyp);\
	if (!pkeyp->get_EVP_PKEY) rb_raise(ePKeyError, "not initialized!");\
} while (0)

/*
 * Classes
 */
ID id_private_q;
VALUE cPKey;
VALUE ePKeyError;

/*
 * Struct
 * see ossl_pkey.h
 */

/*
 * Public
 */
VALUE
ossl_pkey_new(EVP_PKEY *key)
{
	if (!key)
		rb_raise(ePKeyError, "Cannot make new key from NULL.");
	
	switch (key->type) {
#if !defined(NO_RSA) && !defined(OPENSSL_NO_RSA)
		case EVP_PKEY_RSA:
			return ossl_rsa_new(key->pkey.rsa);
#endif
#if !defined(NO_DSA) && !defined(OPENSSL_NO_DSA)
		case EVP_PKEY_DSA:
			return ossl_dsa_new(key->pkey.dsa);
#endif
#if !defined(NO_DH) && !defined(OPENSSL_NO_DH)
		case EVP_PKEY_DH:
			return ossl_dh_new(key->pkey.dh);
#endif
	}
	
	rb_raise(ePKeyError, "unsupported key type");
	return Qnil;
}

VALUE
ossl_pkey_new_from_file(VALUE filename)
{
	FILE *fp = NULL;
	EVP_PKEY *pkey = NULL;
	VALUE obj;

	filename = rb_str_to_str(filename);
	Check_SafeStr(filename);
	
	if ((fp = fopen(RSTRING(filename)->ptr, "r")) == NULL)
		rb_raise(ePKeyError, "%s", strerror(errno));

	/*
	 * MR:
	 * How about PublicKeys from file?
	 * pkey = PEM_read_PublicKey(fp, NULL, NULL, NULL);
	 * MISSING IN OPENSSL
	 */
	/*
	 * Will we handle user passwords?
	 */
	pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL);
	fclose(fp);
	
	if (!pkey)
		OSSL_Raise(ePKeyError, "");

	obj = ossl_pkey_new(pkey);
	EVP_PKEY_free(pkey);

	return obj;
}

EVP_PKEY *
ossl_pkey_get_EVP_PKEY(VALUE obj)
{
	ossl_pkey *pkeyp = NULL;
	
	OSSL_Check_Type(obj, cPKey);

	GetPKey(obj, pkeyp);

	return pkeyp->get_EVP_PKEY(obj);
}

/*
 * Private
 */
static VALUE
ossl_pkey_s_new(int argc, VALUE *argv, VALUE klass)
{
	if (klass == cPKey)
		rb_raise(rb_eNotImpError, "cannot do PKey::ANY.new - it is an abstract class");
	
	return Qnil;
}

/*
 * INIT
 */
void
Init_ossl_pkey(VALUE module)
{
	id_private_q = rb_intern("private?");
	
	ePKeyError = rb_define_class_under(module, "PKeyError", rb_eStandardError);

	cPKey = rb_define_class_under(module, "ANY", rb_cObject);
	rb_define_singleton_method(cPKey, "new", ossl_pkey_s_new, -1);
	
	/*
	 * INIT rsa, dsa
	 */
	Init_ossl_rsa(module, cPKey, ePKeyError);
	Init_ossl_dsa(module, cPKey, ePKeyError);
	Init_ossl_dh(module, cPKey, ePKeyError);
}