1 /*
2  * Copyright (C) 2008-2012 Free Software Foundation, Inc.
3  *
4  * Author: David Marín Carreño
5  *
6  * This file is part of GnuTLS.
7  *
8  * GnuTLS is free software; you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * GnuTLS is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with GnuTLS; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <gnutls/gnutls.h>
31 #include <gnutls/x509.h>
32 #include <gnutls/abstract.h>
33 
34 #include "utils.h"
35 
tls_log_func(int level,const char * str)36 static void tls_log_func(int level, const char *str)
37 {
38 	fprintf(stderr, "%s |<%d>| %s", "crq_key_id", level, str);
39 }
40 
doit(void)41 void doit(void)
42 {
43 	gnutls_x509_privkey_t pkey;
44 	gnutls_privkey_t abs_pkey;
45 	gnutls_x509_crq_t crq;
46 
47 	size_t pkey_key_id_len;
48 	unsigned char *pkey_key_id = NULL;
49 
50 	size_t crq_key_id_len;
51 	unsigned char *crq_key_id = NULL;
52 
53 	gnutls_pk_algorithm_t algorithm;
54 
55 	int ret;
56 
57 	ret = global_init();
58 	if (ret < 0)
59 		fail("global_init: %d\n", ret);
60 
61 	gnutls_global_set_log_function(tls_log_func);
62 	if (debug)
63 		gnutls_global_set_log_level(4711);
64 
65 	for (algorithm = GNUTLS_PK_RSA; algorithm <= GNUTLS_PK_DSA;
66 	     algorithm++) {
67 		ret = gnutls_x509_crq_init(&crq);
68 		if (ret < 0)
69 			fail("gnutls_x509_crq_init: %d: %s\n", ret, gnutls_strerror(ret));
70 
71 		ret = gnutls_x509_privkey_init(&pkey);
72 		if (ret < 0) {
73 			fail("gnutls_x509_privkey_init: %d: %s\n", ret, gnutls_strerror(ret));
74 		}
75 
76 		ret = gnutls_privkey_init(&abs_pkey);
77 		if (ret < 0) {
78 			fail("gnutls_privkey_init: %d: %s\n", ret, gnutls_strerror(ret));
79 		}
80 
81 		ret =
82 		    gnutls_x509_privkey_generate(pkey, algorithm, 2048, 0);
83 		if (ret < 0) {
84 			fail("gnutls_x509_privkey_generate (%s): %d: %s\n",
85 			     gnutls_pk_algorithm_get_name(algorithm),
86 			     ret, gnutls_strerror(ret));
87 		} else if (debug) {
88 			success("Key[%s] generation ok: %d\n",
89 				gnutls_pk_algorithm_get_name(algorithm),
90 				ret);
91 		}
92 
93 		pkey_key_id_len = 0;
94 		ret = gnutls_x509_privkey_get_key_id(pkey, 0, pkey_key_id,
95 						     &pkey_key_id_len);
96 		if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
97 			fail("gnutls_x509_privkey_get_key_id incorrectly returns %d: %s\n", ret, gnutls_strerror(ret));
98 		}
99 
100 		pkey_key_id =
101 		    malloc(sizeof(unsigned char) * pkey_key_id_len);
102 		ret =
103 		    gnutls_x509_privkey_get_key_id(pkey, 0, pkey_key_id,
104 						   &pkey_key_id_len);
105 		if (ret != GNUTLS_E_SUCCESS) {
106 			fail("gnutls_x509_privkey_get_key_id incorrectly returns %d: %s\n", ret, gnutls_strerror(ret));
107 		}
108 
109 		ret = gnutls_x509_crq_set_version(crq, 1);
110 		if (ret < 0) {
111 			fail("gnutls_x509_crq_set_version: %d: %s\n", ret, gnutls_strerror(ret));
112 		}
113 
114 		ret = gnutls_x509_crq_set_key(crq, pkey);
115 		if (ret < 0) {
116 			fail("gnutls_x509_crq_set_key: %d: %s\n", ret, gnutls_strerror(ret));
117 		}
118 
119 		ret =
120 		    gnutls_x509_crq_set_dn_by_oid(crq,
121 						  GNUTLS_OID_X520_COMMON_NAME,
122 						  0, "CN-Test", 7);
123 		if (ret < 0) {
124 			fail("gnutls_x509_crq_set_dn_by_oid: %d: %s\n", ret, gnutls_strerror(ret));
125 		}
126 
127 		ret = gnutls_privkey_import_x509(abs_pkey, pkey, 0);
128 		if (ret < 0) {
129 			fail("gnutls_privkey_import_x509: %d: %s\n", ret, gnutls_strerror(ret));
130 		}
131 
132 		ret =
133 		    gnutls_x509_crq_privkey_sign(crq, abs_pkey,
134 						 GNUTLS_DIG_SHA256, 0);
135 		if (ret < 0) {
136 			fail("gnutls_x509_crq_sign: %d: %s\n", ret, gnutls_strerror(ret));
137 		}
138 
139 		ret = gnutls_x509_crq_verify(crq, 0);
140 		if (ret < 0) {
141 			fail("gnutls_x509_crq_verify: %d: %s\n", ret, gnutls_strerror(ret));
142 		}
143 
144 		crq_key_id_len = 0;
145 		ret =
146 		    gnutls_x509_crq_get_key_id(crq, 0, crq_key_id,
147 						&crq_key_id_len);
148 		if (ret != GNUTLS_E_SHORT_MEMORY_BUFFER) {
149 			fail("gnutls_x509_crq_get_key_id incorrectly returns %d: %s\n", ret, gnutls_strerror(ret));
150 		}
151 
152 		crq_key_id =
153 		    malloc(sizeof(unsigned char) * crq_key_id_len);
154 		ret =
155 		    gnutls_x509_crq_get_key_id(crq, 0, crq_key_id,
156 						&crq_key_id_len);
157 		if (ret != GNUTLS_E_SUCCESS) {
158 			fail("gnutls_x509_crq_get_key_id incorrectly returns %d: %s\n", ret, gnutls_strerror(ret));
159 		}
160 
161 		if (crq_key_id_len == pkey_key_id_len) {
162 			ret =
163 			    memcmp(crq_key_id, pkey_key_id,
164 				   crq_key_id_len);
165 			if (ret == 0) {
166 				if (debug)
167 					success
168 					    ("Key ids are identical. OK.\n");
169 			} else {
170 				fail("Key ids differ incorrectly: %d\n",
171 				     ret);
172 			}
173 		} else {
174 			fail("Key_id lengths differ incorrectly: %d - %d\n", (int) crq_key_id_len, (int) pkey_key_id_len);
175 		}
176 
177 
178 		if (pkey_key_id) {
179 			free(pkey_key_id);
180 			pkey_key_id = NULL;
181 		}
182 
183 		if (crq_key_id) {
184 			free(crq_key_id);
185 			crq_key_id = NULL;
186 		}
187 
188 		gnutls_x509_crq_deinit(crq);
189 		gnutls_x509_privkey_deinit(pkey);
190 		gnutls_privkey_deinit(abs_pkey);
191 	}
192 
193 	gnutls_global_deinit();
194 }
195