1 /* $OpenBSD: x509test.c,v 1.2 2014/11/18 20:51:00 krw 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/param.h> 43 #include <sys/types.h> 44 #include <sys/mman.h> 45 #include <sys/stat.h> 46 #include <ctype.h> 47 #include <fcntl.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <unistd.h> 52 53 #include <sys/socket.h> 54 #include <netinet/in.h> 55 #include <arpa/inet.h> 56 57 #include "conf.h" 58 #include "ipsec_num.h" 59 #include "isakmp_fld.h" 60 #include "libcrypto.h" 61 #include "log.h" 62 #include "math_mp.h" 63 #include "x509.h" 64 65 static int x509_check_subjectaltname (u_char *, u_int, X509 *); 66 67 u_int32_t file_sz; 68 69 #if 0 70 /* XXX Currently unused. */ 71 static u_int8_t * 72 open_file (char *name) 73 { 74 int fd; 75 struct stat st; 76 u_int8_t *addr; 77 78 if (stat (name, &st) == -1) 79 log_fatal ("stat (\"%s\", &st)", name); 80 file_sz = st.st_size; 81 fd = open (name, O_RDONLY); 82 if (fd == -1) 83 log_fatal ("open (\"%s\", O_RDONLY)", name); 84 addr = mmap (0, file_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, 85 fd, 0); 86 if (addr == MAP_FAILED) 87 log_fatal ("mmap (0, %d, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE," 88 "%d, 0)", file_sz, fd); 89 close (fd); 90 91 return addr; 92 } 93 #endif 94 95 /* 96 * Check that a certificate has a subjectAltName and that it matches our ID. 97 */ 98 static int 99 x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert) 100 { 101 u_int8_t *altname; 102 u_int32_t altlen; 103 int type, idtype, ret; 104 105 type = x509_cert_subjectaltname (scert, &altname, &altlen); 106 if (!type) 107 { 108 log_print ("x509_check_subjectaltname: can't access subjectAltName"); 109 return 0; 110 } 111 112 /* 113 * Now that we have the X509 certicate in native form, get the 114 * subjectAltName extension and verify that it matches our ID. 115 */ 116 117 /* XXX Get type of ID. */ 118 idtype = id[0]; 119 id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; 120 id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ; 121 122 ret = 0; 123 switch (idtype) 124 { 125 case IPSEC_ID_IPV4_ADDR: 126 if (type == X509v3_IP_ADDR) 127 ret = 1; 128 break; 129 case IPSEC_ID_FQDN: 130 if (type == X509v3_DNS_NAME) 131 ret = 1; 132 break; 133 case IPSEC_ID_USER_FQDN: 134 if (type == X509v3_RFC_NAME) 135 ret = 1; 136 break; 137 default: 138 ret = 0; 139 break; 140 } 141 142 if (!ret) 143 { 144 LOG_DBG ((LOG_CRYPTO, 50, 145 "x509_check_subjectaltname: " 146 "our ID type (%d) does not match X509 cert ID type (%d)", 147 idtype, type)); 148 return 0; 149 } 150 151 if (altlen != id_len || memcmp (altname, id, id_len) != 0) 152 { 153 LOG_DBG ((LOG_CRYPTO, 50, 154 "x509_check_subjectaltname: " 155 "our ID does not match X509 cert ID")); 156 return 0; 157 } 158 159 return 1; 160 } 161 162 int 163 main (int argc, char *argv[]) 164 { 165 RSA *pub_key, *priv_key; 166 X509 *cert; 167 BIO *certfile, *keyfile; 168 EVP_PKEY *pkey_pub; 169 u_char ipaddr[6]; 170 struct in_addr saddr; 171 char enc[256], dec[256]; 172 u_int8_t idpayload[8]; 173 int err, len; 174 175 if (argc < 3 || argc > 4) 176 { 177 fprintf (stderr, "usage: x509test private-key certificate ip-address\n"); 178 exit (1); 179 } 180 181 /* 182 * X509_verify will fail, as will all other functions that call 183 * EVP_get_digest_byname. 184 */ 185 186 libcrypto_init (); 187 188 printf ("Reading private key %s\n", argv[1]); 189 keyfile = BIO_new (BIO_s_file ()); 190 if (BIO_read_filename (keyfile, argv[1]) == -1) 191 { 192 perror ("read"); 193 exit (1); 194 } 195 #if SSLEAY_VERSION_NUMBER >= 0x00904100L 196 priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL, NULL); 197 #else 198 priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL); 199 #endif 200 BIO_free (keyfile); 201 if (priv_key == NULL) 202 { 203 printf("PEM_read_bio_RSAPrivateKey () failed\n"); 204 exit (1); 205 } 206 207 /* Use a certificate created by ssleay. */ 208 printf ("Reading ssleay created certificate %s\n", argv[2]); 209 certfile = BIO_new (BIO_s_file ()); 210 if (BIO_read_filename (certfile, argv[2]) == -1) 211 { 212 perror ("read"); 213 exit (1); 214 } 215 #if SSLEAY_VERSION_NUMBER >= 0x00904100L 216 cert = PEM_read_bio_X509 (certfile, NULL, NULL, NULL); 217 #else 218 cert = PEM_read_bio_X509 (certfile, NULL, NULL); 219 #endif 220 BIO_free (certfile); 221 if (cert == NULL) 222 { 223 printf("PEM_read_bio_X509 () failed\n"); 224 exit (1); 225 } 226 227 pkey_pub = X509_get_pubkey (cert); 228 /* XXX Violation of the interface? */ 229 pub_key = pkey_pub->pkey.rsa; 230 if (pub_key == NULL) 231 { 232 exit (1); 233 } 234 235 printf ("Testing RSA keys: "); 236 237 err = 0; 238 strlcpy (dec, "Eine kleine Testmeldung", 256); 239 if ((len = RSA_private_encrypt (strlen (dec), dec, enc, priv_key, 240 RSA_PKCS1_PADDING)) == -1) 241 242 printf ("SIGN FAILED "); 243 else 244 err = RSA_public_decrypt (len, enc, dec, pub_key, RSA_PKCS1_PADDING); 245 246 if (err == -1 || strcmp (dec, "Eine kleine Testmeldung")) 247 printf ("SIGN/VERIFY FAILED"); 248 else 249 printf ("OKAY"); 250 printf ("\n"); 251 252 253 printf ("Validate SIGNED: "); 254 err = X509_verify (cert, pkey_pub); 255 printf ("X509 verify: %d ", err); 256 if (err == -1) 257 printf ("FAILED "); 258 else 259 printf ("OKAY "); 260 printf ("\n"); 261 262 if (argc == 4) 263 { 264 printf ("Verifying extension: "); 265 if (inet_aton (argv[3], &saddr) == 0) 266 { 267 printf ("inet_aton () failed\n"); 268 exit (1); 269 } 270 271 saddr.s_addr = htonl (saddr.s_addr); 272 ipaddr[0] = 0x87; 273 ipaddr[1] = 0x04; 274 ipaddr[2] = saddr.s_addr >> 24; 275 ipaddr[3] = (saddr.s_addr >> 16) & 0xff; 276 ipaddr[4] = (saddr.s_addr >> 8) & 0xff; 277 ipaddr[5] = saddr.s_addr & 0xff; 278 bzero (idpayload, sizeof idpayload); 279 idpayload[0] = IPSEC_ID_IPV4_ADDR; 280 bcopy (ipaddr + 2, idpayload + 4, 4); 281 282 if (!x509_check_subjectaltname (idpayload, sizeof idpayload, cert)) 283 printf("FAILED "); 284 else 285 printf("OKAY "); 286 printf ("\n"); 287 } 288 289 return 1; 290 } 291