xref: /openbsd-src/regress/sbin/isakmpd/x509/x509test.c (revision 49a6e16f2c2c8e509184b1f777366d1a6f337e1c)
1*49a6e16fSderaadt /*	$OpenBSD: x509test.c,v 1.3 2021/12/13 16:56:49 deraadt Exp $	*/
271ec8d3aScloder /*	$EOM: x509test.c,v 1.9 2000/12/21 15:24:25 ho Exp $	*/
371ec8d3aScloder 
471ec8d3aScloder /*
571ec8d3aScloder  * Copyright (c) 1998, 1999 Niels Provos.  All rights reserved.
671ec8d3aScloder  * Copyright (c) 1999, 2001 Niklas Hallqvist.  All rights reserved.
771ec8d3aScloder  * Copyright (c) 2001 H�kan Olsson.  All rights reserved.
871ec8d3aScloder  *
971ec8d3aScloder  * Redistribution and use in source and binary forms, with or without
1071ec8d3aScloder  * modification, are permitted provided that the following conditions
1171ec8d3aScloder  * are met:
1271ec8d3aScloder  * 1. Redistributions of source code must retain the above copyright
1371ec8d3aScloder  *    notice, this list of conditions and the following disclaimer.
1471ec8d3aScloder  * 2. Redistributions in binary form must reproduce the above copyright
1571ec8d3aScloder  *    notice, this list of conditions and the following disclaimer in the
1671ec8d3aScloder  *    documentation and/or other materials provided with the distribution.
1771ec8d3aScloder  *
1871ec8d3aScloder  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1971ec8d3aScloder  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2071ec8d3aScloder  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2171ec8d3aScloder  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2271ec8d3aScloder  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2371ec8d3aScloder  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2471ec8d3aScloder  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2571ec8d3aScloder  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2671ec8d3aScloder  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2771ec8d3aScloder  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2871ec8d3aScloder  */
2971ec8d3aScloder 
3071ec8d3aScloder /*
3171ec8d3aScloder  * This code was written under funding by Ericsson Radio Systems.
3271ec8d3aScloder  */
3371ec8d3aScloder 
3471ec8d3aScloder /*
3571ec8d3aScloder  * This program takes a certificate generated by ssleay and a key pair
3671ec8d3aScloder  * from rsakeygen. It reads the IP address from certificate.txt and
3771ec8d3aScloder  * includes this as subject alt name extension into the certifcate.
3871ec8d3aScloder  * The result gets written as new certificate that can be used by
3971ec8d3aScloder  * isakmpd.
4071ec8d3aScloder  */
4171ec8d3aScloder 
4271ec8d3aScloder #include <sys/types.h>
4371ec8d3aScloder #include <sys/mman.h>
4471ec8d3aScloder #include <sys/stat.h>
4571ec8d3aScloder #include <ctype.h>
4671ec8d3aScloder #include <fcntl.h>
4771ec8d3aScloder #include <stdio.h>
4871ec8d3aScloder #include <stdlib.h>
4971ec8d3aScloder #include <string.h>
5071ec8d3aScloder #include <unistd.h>
5171ec8d3aScloder 
5271ec8d3aScloder #include <sys/socket.h>
5371ec8d3aScloder #include <netinet/in.h>
5471ec8d3aScloder #include <arpa/inet.h>
5571ec8d3aScloder 
5671ec8d3aScloder #include "conf.h"
5771ec8d3aScloder #include "ipsec_num.h"
5871ec8d3aScloder #include "isakmp_fld.h"
5971ec8d3aScloder #include "libcrypto.h"
6071ec8d3aScloder #include "log.h"
6171ec8d3aScloder #include "math_mp.h"
6271ec8d3aScloder #include "x509.h"
6371ec8d3aScloder 
6471ec8d3aScloder static int x509_check_subjectaltname (u_char *, u_int, X509 *);
6571ec8d3aScloder 
6671ec8d3aScloder u_int32_t file_sz;
6771ec8d3aScloder 
6871ec8d3aScloder #if 0
6971ec8d3aScloder /* XXX Currently unused.  */
7071ec8d3aScloder static u_int8_t *
7171ec8d3aScloder open_file (char *name)
7271ec8d3aScloder {
7371ec8d3aScloder   int fd;
7471ec8d3aScloder   struct stat st;
7571ec8d3aScloder   u_int8_t *addr;
7671ec8d3aScloder 
7771ec8d3aScloder   if (stat (name, &st) == -1)
7871ec8d3aScloder     log_fatal ("stat (\"%s\", &st)", name);
7971ec8d3aScloder   file_sz = st.st_size;
8071ec8d3aScloder   fd = open (name, O_RDONLY);
8171ec8d3aScloder   if (fd == -1)
8271ec8d3aScloder     log_fatal ("open (\"%s\", O_RDONLY)", name);
8371ec8d3aScloder   addr = mmap (0, file_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,
8471ec8d3aScloder 	       fd, 0);
8571ec8d3aScloder   if (addr == MAP_FAILED)
8671ec8d3aScloder     log_fatal ("mmap (0, %d, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE,"
8771ec8d3aScloder 	       "%d, 0)", file_sz, fd);
8871ec8d3aScloder   close (fd);
8971ec8d3aScloder 
9071ec8d3aScloder   return addr;
9171ec8d3aScloder }
9271ec8d3aScloder #endif
9371ec8d3aScloder 
9471ec8d3aScloder /*
9571ec8d3aScloder  * Check that a certificate has a subjectAltName and that it matches our ID.
9671ec8d3aScloder  */
9771ec8d3aScloder static int
x509_check_subjectaltname(u_char * id,u_int id_len,X509 * scert)9871ec8d3aScloder x509_check_subjectaltname (u_char *id, u_int id_len, X509 *scert)
9971ec8d3aScloder {
10071ec8d3aScloder   u_int8_t *altname;
10171ec8d3aScloder   u_int32_t altlen;
10271ec8d3aScloder   int type, idtype, ret;
10371ec8d3aScloder 
10471ec8d3aScloder   type = x509_cert_subjectaltname (scert, &altname, &altlen);
10571ec8d3aScloder   if (!type)
10671ec8d3aScloder     {
10771ec8d3aScloder       log_print ("x509_check_subjectaltname: can't access subjectAltName");
10871ec8d3aScloder       return 0;
10971ec8d3aScloder     }
11071ec8d3aScloder 
11171ec8d3aScloder   /*
11271ec8d3aScloder    * Now that we have the X509 certicate in native form, get the
11371ec8d3aScloder    * subjectAltName extension and verify that it matches our ID.
11471ec8d3aScloder    */
11571ec8d3aScloder 
11671ec8d3aScloder   /* XXX Get type of ID.  */
11771ec8d3aScloder   idtype = id[0];
11871ec8d3aScloder   id += ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
11971ec8d3aScloder   id_len -= ISAKMP_ID_DATA_OFF - ISAKMP_GEN_SZ;
12071ec8d3aScloder 
12171ec8d3aScloder   ret = 0;
12271ec8d3aScloder   switch (idtype)
12371ec8d3aScloder     {
12471ec8d3aScloder     case IPSEC_ID_IPV4_ADDR:
12571ec8d3aScloder       if (type == X509v3_IP_ADDR)
12671ec8d3aScloder 	ret = 1;
12771ec8d3aScloder       break;
12871ec8d3aScloder     case IPSEC_ID_FQDN:
12971ec8d3aScloder       if (type == X509v3_DNS_NAME)
13071ec8d3aScloder 	ret = 1;
13171ec8d3aScloder       break;
13271ec8d3aScloder     case IPSEC_ID_USER_FQDN:
13371ec8d3aScloder       if (type == X509v3_RFC_NAME)
13471ec8d3aScloder 	ret = 1;
13571ec8d3aScloder       break;
13671ec8d3aScloder     default:
13771ec8d3aScloder       ret = 0;
13871ec8d3aScloder       break;
13971ec8d3aScloder     }
14071ec8d3aScloder 
14171ec8d3aScloder   if (!ret)
14271ec8d3aScloder     {
14371ec8d3aScloder       LOG_DBG ((LOG_CRYPTO, 50,
14471ec8d3aScloder 		"x509_check_subjectaltname: "
14571ec8d3aScloder 		"our ID type (%d) does not match X509 cert ID type (%d)",
14671ec8d3aScloder 		idtype, type));
14771ec8d3aScloder       return 0;
14871ec8d3aScloder     }
14971ec8d3aScloder 
15071ec8d3aScloder   if (altlen != id_len || memcmp (altname, id, id_len) != 0)
15171ec8d3aScloder     {
15271ec8d3aScloder       LOG_DBG ((LOG_CRYPTO, 50,
15371ec8d3aScloder 		"x509_check_subjectaltname: "
15471ec8d3aScloder 		"our ID does not match X509 cert ID"));
15571ec8d3aScloder       return 0;
15671ec8d3aScloder     }
15771ec8d3aScloder 
15871ec8d3aScloder   return 1;
15971ec8d3aScloder }
16071ec8d3aScloder 
16171ec8d3aScloder int
main(int argc,char * argv[])16271ec8d3aScloder main (int argc, char *argv[])
16371ec8d3aScloder {
16471ec8d3aScloder   RSA *pub_key, *priv_key;
16571ec8d3aScloder   X509 *cert;
16671ec8d3aScloder   BIO *certfile, *keyfile;
16771ec8d3aScloder   EVP_PKEY *pkey_pub;
16871ec8d3aScloder   u_char ipaddr[6];
16971ec8d3aScloder   struct in_addr saddr;
17071ec8d3aScloder   char enc[256], dec[256];
17171ec8d3aScloder   u_int8_t idpayload[8];
17271ec8d3aScloder   int err, len;
17371ec8d3aScloder 
17471ec8d3aScloder   if (argc < 3 || argc > 4)
17571ec8d3aScloder     {
17671ec8d3aScloder       fprintf (stderr, "usage: x509test private-key certificate ip-address\n");
17771ec8d3aScloder       exit (1);
17871ec8d3aScloder     }
17971ec8d3aScloder 
18071ec8d3aScloder   /*
18171ec8d3aScloder    * X509_verify will fail, as will all other functions that call
18271ec8d3aScloder    * EVP_get_digest_byname.
18371ec8d3aScloder    */
18471ec8d3aScloder 
18571ec8d3aScloder   libcrypto_init ();
18671ec8d3aScloder 
18771ec8d3aScloder   printf ("Reading private key %s\n", argv[1]);
18871ec8d3aScloder   keyfile = BIO_new (BIO_s_file ());
18971ec8d3aScloder   if (BIO_read_filename (keyfile, argv[1]) == -1)
19071ec8d3aScloder     {
19171ec8d3aScloder       perror ("read");
19271ec8d3aScloder       exit (1);
19371ec8d3aScloder     }
19471ec8d3aScloder #if SSLEAY_VERSION_NUMBER >= 0x00904100L
19571ec8d3aScloder   priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL, NULL);
19671ec8d3aScloder #else
19771ec8d3aScloder   priv_key = PEM_read_bio_RSAPrivateKey (keyfile, NULL, NULL);
19871ec8d3aScloder #endif
19971ec8d3aScloder   BIO_free (keyfile);
20071ec8d3aScloder   if (priv_key == NULL)
20171ec8d3aScloder     {
20271ec8d3aScloder       printf("PEM_read_bio_RSAPrivateKey () failed\n");
20371ec8d3aScloder       exit (1);
20471ec8d3aScloder     }
20571ec8d3aScloder 
20671ec8d3aScloder   /* Use a certificate created by ssleay.  */
20771ec8d3aScloder   printf ("Reading ssleay created certificate %s\n", argv[2]);
20871ec8d3aScloder   certfile = BIO_new (BIO_s_file ());
20971ec8d3aScloder   if (BIO_read_filename (certfile, argv[2]) == -1)
21071ec8d3aScloder     {
21171ec8d3aScloder       perror ("read");
21271ec8d3aScloder       exit (1);
21371ec8d3aScloder     }
21471ec8d3aScloder #if SSLEAY_VERSION_NUMBER >= 0x00904100L
21571ec8d3aScloder   cert = PEM_read_bio_X509 (certfile, NULL, NULL, NULL);
21671ec8d3aScloder #else
21771ec8d3aScloder   cert = PEM_read_bio_X509 (certfile, NULL, NULL);
21871ec8d3aScloder #endif
21971ec8d3aScloder   BIO_free (certfile);
22071ec8d3aScloder   if (cert == NULL)
22171ec8d3aScloder     {
22271ec8d3aScloder       printf("PEM_read_bio_X509 () failed\n");
22371ec8d3aScloder       exit (1);
22471ec8d3aScloder     }
22571ec8d3aScloder 
22671ec8d3aScloder   pkey_pub = X509_get_pubkey (cert);
22771ec8d3aScloder   /* XXX Violation of the interface?  */
22871ec8d3aScloder   pub_key = pkey_pub->pkey.rsa;
22971ec8d3aScloder   if (pub_key == NULL)
23071ec8d3aScloder     {
23171ec8d3aScloder       exit (1);
23271ec8d3aScloder     }
23371ec8d3aScloder 
23471ec8d3aScloder   printf ("Testing RSA keys: ");
23571ec8d3aScloder 
23671ec8d3aScloder   err = 0;
23771ec8d3aScloder   strlcpy (dec, "Eine kleine Testmeldung", 256);
23871ec8d3aScloder   if ((len = RSA_private_encrypt (strlen (dec), dec, enc, priv_key,
23971ec8d3aScloder 				  RSA_PKCS1_PADDING)) == -1)
24071ec8d3aScloder 
24171ec8d3aScloder     printf ("SIGN FAILED ");
24271ec8d3aScloder   else
24371ec8d3aScloder     err = RSA_public_decrypt (len, enc, dec, pub_key, RSA_PKCS1_PADDING);
24471ec8d3aScloder 
24571ec8d3aScloder   if (err == -1 || strcmp (dec, "Eine kleine Testmeldung"))
24671ec8d3aScloder     printf ("SIGN/VERIFY FAILED");
24771ec8d3aScloder   else
24871ec8d3aScloder     printf ("OKAY");
24971ec8d3aScloder   printf ("\n");
25071ec8d3aScloder 
25171ec8d3aScloder 
25271ec8d3aScloder   printf ("Validate SIGNED: ");
25371ec8d3aScloder   err = X509_verify (cert, pkey_pub);
25471ec8d3aScloder   printf ("X509 verify: %d ", err);
25571ec8d3aScloder   if (err == -1)
25671ec8d3aScloder     printf ("FAILED ");
25771ec8d3aScloder   else
25871ec8d3aScloder     printf ("OKAY ");
25971ec8d3aScloder   printf ("\n");
26071ec8d3aScloder 
26171ec8d3aScloder   if (argc == 4)
26271ec8d3aScloder     {
26371ec8d3aScloder       printf ("Verifying extension: ");
26471ec8d3aScloder       if (inet_aton (argv[3], &saddr) == 0)
26571ec8d3aScloder 	{
26671ec8d3aScloder 	  printf ("inet_aton () failed\n");
26771ec8d3aScloder 	  exit (1);
26871ec8d3aScloder 	}
26971ec8d3aScloder 
27071ec8d3aScloder       saddr.s_addr = htonl (saddr.s_addr);
27171ec8d3aScloder       ipaddr[0] = 0x87;
27271ec8d3aScloder       ipaddr[1] = 0x04;
27371ec8d3aScloder       ipaddr[2] = saddr.s_addr >> 24;
27471ec8d3aScloder       ipaddr[3] = (saddr.s_addr >> 16) & 0xff;
27571ec8d3aScloder       ipaddr[4] = (saddr.s_addr >> 8) & 0xff;
27671ec8d3aScloder       ipaddr[5] = saddr.s_addr & 0xff;
27771ec8d3aScloder       bzero (idpayload, sizeof idpayload);
27871ec8d3aScloder       idpayload[0] = IPSEC_ID_IPV4_ADDR;
27971ec8d3aScloder       bcopy (ipaddr + 2, idpayload + 4, 4);
28071ec8d3aScloder 
28171ec8d3aScloder       if (!x509_check_subjectaltname (idpayload, sizeof idpayload, cert))
28271ec8d3aScloder 	printf("FAILED ");
28371ec8d3aScloder       else
28471ec8d3aScloder 	printf("OKAY ");
28571ec8d3aScloder       printf ("\n");
28671ec8d3aScloder     }
28771ec8d3aScloder 
28871ec8d3aScloder   return 1;
28971ec8d3aScloder }
290