1 /* $OpenBSD: x509test.c,v 1.3 2021/12/13 16:56:49 deraadt Exp $ */
2 /* $EOM: x509test.c,v 1.9 2000/12/21 15:24:25 ho Exp $ */
3
4 /*
5 * Copyright (c) 1998, 1999 Niels Provos. All rights reserved.
6 * Copyright (c) 1999, 2001 Niklas Hallqvist. All rights reserved.
7 * Copyright (c) 2001 H�kan Olsson. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /*
31 * This code was written under funding by Ericsson Radio Systems.
32 */
33
34 /*
35 * This program takes a certificate generated by ssleay and a key pair
36 * from rsakeygen. It reads the IP address from certificate.txt and
37 * includes this as subject alt name extension into the certifcate.
38 * The result gets written as new certificate that can be used by
39 * isakmpd.
40 */
41
42 #include <sys/types.h>
43 #include <sys/mman.h>
44 #include <sys/stat.h>
45 #include <ctype.h>
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51
52 #include <sys/socket.h>
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55
56 #include "conf.h"
57 #include "ipsec_num.h"
58 #include "isakmp_fld.h"
59 #include "libcrypto.h"
60 #include "log.h"
61 #include "math_mp.h"
62 #include "x509.h"
63
64 static int x509_check_subjectaltname (u_char *, u_int, X509 *);
65
66 u_int32_t file_sz;
67
68 #if 0
69 /* XXX Currently unused. */
70 static u_int8_t *
71 open_file (char *name)
72 {
73 int fd;
74 struct stat st;
75 u_int8_t *addr;
76
77 if (stat (name, &st) == -1)
78 log_fatal ("stat (\"%s\", &st)", name);
79 file_sz = st.st_size;
80 fd = open (name, O_RDONLY);
81 if (fd == -1)
82 log_fatal ("open (\"%s\", O_RDONLY)", name);
83 addr = mmap (0, file_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
84 fd, 0);
85 if (addr == MAP_FAILED)
86 log_fatal ("mmap (0, %d, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,"
87 "%d, 0)", file_sz, fd);
88 close (fd);
89
90 return addr;
91 }
92 #endif
93
94 /*
95 * Check that a certificate has a subjectAltName and that it matches our ID.
96 */
97 static int
x509_check_subjectaltname(u_char * id,u_int id_len,X509 * scert)98 x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert)
99 {
100 u_int8_t *altname;
101 u_int32_t altlen;
102 int type, idtype, ret;
103
104 type = x509_cert_subjectaltname (scert, &altname, &altlen);
105 if (!type)
106 {
107 log_print ("x509_check_subjectaltname: can't access subjectAltName");
108 return 0;
109 }
110
111 /*
112 * Now that we have the X509 certicate in native form, get the
113 * subjectAltName extension and verify that it matches our ID.
114 */
115
116 /* XXX Get type of ID. */
117 idtype = id[0];
118 id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
119 id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
120
121 ret = 0;
122 switch (idtype)
123 {
124 case IPSEC_ID_IPV4_ADDR:
125 if (type == X509v3_IP_ADDR)
126 ret = 1;
127 break;
128 case IPSEC_ID_FQDN:
129 if (type == X509v3_DNS_NAME)
130 ret = 1;
131 break;
132 case IPSEC_ID_USER_FQDN:
133 if (type == X509v3_RFC_NAME)
134 ret = 1;
135 break;
136 default:
137 ret = 0;
138 break;
139 }
140
141 if (!ret)
142 {
143 LOG_DBG ((LOG_CRYPTO, 50,
144 "x509_check_subjectaltname: "
145 "our ID type (%d) does not match X509 cert ID type (%d)",
146 idtype, type));
147 return 0;
148 }
149
150 if (altlen != id_len || memcmp (altname, id, id_len) != 0)
151 {
152 LOG_DBG ((LOG_CRYPTO, 50,
153 "x509_check_subjectaltname: "
154 "our ID does not match X509 cert ID"));
155 return 0;
156 }
157
158 return 1;
159 }
160
161 int
main(int argc,char * argv[])162 main (int argc, char *argv[])
163 {
164 RSA *pub_key, *priv_key;
165 X509 *cert;
166 BIO *certfile, *keyfile;
167 EVP_PKEY *pkey_pub;
168 u_char ipaddr[6];
169 struct in_addr saddr;
170 char enc[256], dec[256];
171 u_int8_t idpayload[8];
172 int err, len;
173
174 if (argc < 3 || argc > 4)
175 {
176 fprintf (stderr, "usage: x509test private-key certificate ip-address\n");
177 exit (1);
178 }
179
180 /*
181 * X509_verify will fail, as will all other functions that call
182 * EVP_get_digest_byname.
183 */
184
185 libcrypto_init ();
186
187 printf ("Reading private key %s\n", argv[1]);
188 keyfile = BIO_new (BIO_s_file ());
189 if (BIO_read_filename (keyfile, argv[1]) == -1)
190 {
191 perror ("read");
192 exit (1);
193 }
194 #if SSLEAY_VERSION_NUMBER >= 0x00904100L
195 priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL, NULL);
196 #else
197 priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL);
198 #endif
199 BIO_free (keyfile);
200 if (priv_key == NULL)
201 {
202 printf("PEM_read_bio_RSAPrivateKey () failed\n");
203 exit (1);
204 }
205
206 /* Use a certificate created by ssleay. */
207 printf ("Reading ssleay created certificate %s\n", argv[2]);
208 certfile = BIO_new (BIO_s_file ());
209 if (BIO_read_filename (certfile, argv[2]) == -1)
210 {
211 perror ("read");
212 exit (1);
213 }
214 #if SSLEAY_VERSION_NUMBER >= 0x00904100L
215 cert = PEM_read_bio_X509 (certfile, NULL, NULL, NULL);
216 #else
217 cert = PEM_read_bio_X509 (certfile, NULL, NULL);
218 #endif
219 BIO_free (certfile);
220 if (cert == NULL)
221 {
222 printf("PEM_read_bio_X509 () failed\n");
223 exit (1);
224 }
225
226 pkey_pub = X509_get_pubkey (cert);
227 /* XXX Violation of the interface? */
228 pub_key = pkey_pub->pkey.rsa;
229 if (pub_key == NULL)
230 {
231 exit (1);
232 }
233
234 printf ("Testing RSA keys: ");
235
236 err = 0;
237 strlcpy (dec, "Eine kleine Testmeldung", 256);
238 if ((len = RSA_private_encrypt (strlen (dec), dec, enc, priv_key,
239 RSA_PKCS1_PADDING)) == -1)
240
241 printf ("SIGN FAILED ");
242 else
243 err = RSA_public_decrypt (len, enc, dec, pub_key, RSA_PKCS1_PADDING);
244
245 if (err == -1 || strcmp (dec, "Eine kleine Testmeldung"))
246 printf ("SIGN/VERIFY FAILED");
247 else
248 printf ("OKAY");
249 printf ("\n");
250
251
252 printf ("Validate SIGNED: ");
253 err = X509_verify (cert, pkey_pub);
254 printf ("X509 verify: %d ", err);
255 if (err == -1)
256 printf ("FAILED ");
257 else
258 printf ("OKAY ");
259 printf ("\n");
260
261 if (argc == 4)
262 {
263 printf ("Verifying extension: ");
264 if (inet_aton (argv[3], &saddr) == 0)
265 {
266 printf ("inet_aton () failed\n");
267 exit (1);
268 }
269
270 saddr.s_addr = htonl (saddr.s_addr);
271 ipaddr[0] = 0x87;
272 ipaddr[1] = 0x04;
273 ipaddr[2] = saddr.s_addr >> 24;
274 ipaddr[3] = (saddr.s_addr >> 16) & 0xff;
275 ipaddr[4] = (saddr.s_addr >> 8) & 0xff;
276 ipaddr[5] = saddr.s_addr & 0xff;
277 bzero (idpayload, sizeof idpayload);
278 idpayload[0] = IPSEC_ID_IPV4_ADDR;
279 bcopy (ipaddr + 2, idpayload + 4, 4);
280
281 if (!x509_check_subjectaltname (idpayload, sizeof idpayload, cert))
282 printf("FAILED ");
283 else
284 printf("OKAY ");
285 printf ("\n");
286 }
287
288 return 1;
289 }
290