1 /*
2 * Copyright (C) 2017 Red Hat, Inc.
3 *
4 * Author: Nikos Mavrogiannopoulos
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 <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 #include <unistd.h>
32
33 #include <gnutls/gnutls.h>
34 #include <gnutls/x509.h>
35 #include <gnutls/abstract.h>
36
37 #include "../utils.h"
38 #include "softhsm.h"
39
40 /* Tests whether a protected object is imported with PIN obtained using
41 * pin-value or pin-source. */
42
43 #define CONFIG_NAME "softhsm-import-with-pin"
44 #define CONFIG CONFIG_NAME".config"
45
46 #include "../cert-common.h"
47
48 #define PIN "1234"
49
50 static const gnutls_datum_t testdata = {(void*)"test test", 9};
51
tls_log_func(int level,const char * str)52 static void tls_log_func(int level, const char *str)
53 {
54 fprintf(stderr, "|<%d>| %s", level, str);
55 }
56
57 static
pin_func(void * userdata,int attempt,const char * url,const char * label,unsigned flags,char * pin,size_t pin_max)58 int pin_func(void* userdata, int attempt, const char* url, const char *label,
59 unsigned flags, char *pin, size_t pin_max)
60 {
61 if (attempt == 0) {
62 strcpy(pin, PIN);
63 return 0;
64 }
65 return -1;
66 }
67
write_pin(const char * file,const char * pin)68 static void write_pin(const char *file, const char *pin)
69 {
70 FILE *fp = fopen(file, "w");
71 assert(fp != NULL);
72 fputs(pin, fp);
73 fclose(fp);
74 }
75
doit(void)76 void doit(void)
77 {
78 char buf[512];
79 int ret;
80 const char *lib, *bin;
81 gnutls_x509_privkey_t key;
82 gnutls_datum_t sig;
83 gnutls_privkey_t pkey;
84 char file[TMPNAME_SIZE];
85
86 bin = softhsm_bin();
87
88 lib = softhsm_lib();
89
90 ret = global_init();
91 if (ret != 0) {
92 fail("%d: %s\n", ret, gnutls_strerror(ret));
93 exit(1);
94 }
95
96 gnutls_pkcs11_set_pin_function(pin_func, NULL);
97 gnutls_global_set_log_function(tls_log_func);
98 if (debug)
99 gnutls_global_set_log_level(4711);
100
101 set_softhsm_conf(CONFIG);
102 snprintf(buf, sizeof(buf), "%s --init-token --slot 0 --label test --so-pin "PIN" --pin "PIN, bin);
103 system(buf);
104
105 ret = gnutls_pkcs11_add_provider(lib, "trusted");
106 if (ret < 0) {
107 fprintf(stderr, "add_provider: %s\n",
108 gnutls_strerror(ret));
109 exit(1);
110 }
111
112 ret = gnutls_x509_privkey_init(&key);
113 if (ret < 0) {
114 fprintf(stderr,
115 "gnutls_x509_privkey_init: %s\n",
116 gnutls_strerror(ret));
117 exit(1);
118 }
119
120 ret =
121 gnutls_x509_privkey_import(key, &server_key,
122 GNUTLS_X509_FMT_PEM);
123 if (ret < 0) {
124 fprintf(stderr,
125 "gnutls_x509_privkey_import: %s\n",
126 gnutls_strerror(ret));
127 exit(1);
128 }
129
130 /* initialize softhsm token */
131 ret = gnutls_pkcs11_token_init(SOFTHSM_URL, PIN, "test");
132 if (ret < 0) {
133 fail("gnutls_pkcs11_token_init: %s\n", gnutls_strerror(ret));
134 exit(1);
135 }
136
137 ret = gnutls_pkcs11_token_set_pin(SOFTHSM_URL, NULL, PIN, GNUTLS_PIN_USER);
138 if (ret < 0) {
139 fail("gnutls_pkcs11_token_set_pin: %s\n", gnutls_strerror(ret));
140 exit(1);
141 }
142
143 ret = gnutls_pkcs11_copy_x509_privkey(SOFTHSM_URL, key, "cert", GNUTLS_KEY_DIGITAL_SIGNATURE|GNUTLS_KEY_KEY_ENCIPHERMENT,
144 GNUTLS_PKCS11_OBJ_FLAG_MARK_PRIVATE|GNUTLS_PKCS11_OBJ_FLAG_MARK_SENSITIVE|GNUTLS_PKCS11_OBJ_FLAG_LOGIN);
145 if (ret < 0) {
146 fail("gnutls_pkcs11_copy_x509_privkey: %s\n", gnutls_strerror(ret));
147 exit(1);
148 }
149
150 gnutls_x509_privkey_deinit(key);
151 gnutls_pkcs11_set_pin_function(NULL, NULL);
152
153 assert(gnutls_privkey_init(&pkey) == 0);
154
155 /* Test 1
156 * Try importing with wrong pin-value */
157 ret = gnutls_privkey_import_pkcs11_url(pkey, SOFTHSM_URL";object=cert;object-type=private;pin-value=XXXX");
158 if (ret != GNUTLS_E_PKCS11_PIN_ERROR) {
159 fprintf(stderr, "unexpected error in %d: %s\n", __LINE__, gnutls_strerror(ret));
160 exit(1);
161 }
162 gnutls_privkey_deinit(pkey);
163 assert(gnutls_privkey_init(&pkey) == 0);
164
165 /* Test 2
166 * Try importing with pin-value */
167 ret = gnutls_privkey_import_pkcs11_url(pkey, SOFTHSM_URL";object=cert;object-type=private;pin-value="PIN);
168 if (ret < 0) {
169 fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
170 exit(1);
171 }
172
173 /* check whether privkey is operational by signing */
174 assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
175 gnutls_free(sig.data);
176 gnutls_privkey_deinit(pkey);
177
178 /* Test 3
179 * Try importing with wrong pin-source */
180 track_temp_files();
181 get_tmpname(file);
182
183 write_pin(file, "XXXX");
184
185 assert(gnutls_privkey_init(&pkey) == 0);
186 snprintf(buf, sizeof(buf), "%s;object=cert;object-type=private;pin-source=%s", SOFTHSM_URL, file);
187 ret = gnutls_privkey_import_pkcs11_url(pkey, buf);
188 if (ret != GNUTLS_E_PKCS11_PIN_ERROR) {
189 fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
190 exit(1);
191 }
192
193 gnutls_privkey_deinit(pkey);
194
195 /* Test 4
196 * Try importing with pin-source */
197 write_pin(file, PIN);
198
199 assert(gnutls_privkey_init(&pkey) == 0);
200 snprintf(buf, sizeof(buf), "%s;object=cert;object-type=private;pin-source=%s", SOFTHSM_URL, file);
201 ret = gnutls_privkey_import_pkcs11_url(pkey, buf);
202 if (ret < 0) {
203 fprintf(stderr, "error in %d: %s\n", __LINE__, gnutls_strerror(ret));
204 exit(1);
205 }
206
207 /* check whether privkey is operational by signing */
208 assert(gnutls_privkey_sign_data(pkey, GNUTLS_DIG_SHA256, 0, &testdata, &sig) == 0);
209 gnutls_free(sig.data);
210 gnutls_privkey_deinit(pkey);
211
212 gnutls_global_deinit();
213 delete_temp_files();
214
215 remove(CONFIG);
216 }
217
218