xref: /openbsd-src/sbin/iked/crypto.c (revision fa353a8f9b716432e67aba95e7a4beea67b6c3b5)
1*fa353a8fSclaudio /*	$OpenBSD: crypto.c,v 1.47 2024/11/21 13:26:49 claudio Exp $	*/
245ae9d61Sreyk 
345ae9d61Sreyk /*
4fcebd35dSreyk  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
545ae9d61Sreyk  *
645ae9d61Sreyk  * Permission to use, copy, modify, and distribute this software for any
745ae9d61Sreyk  * purpose with or without fee is hereby granted, provided that the above
845ae9d61Sreyk  * copyright notice and this permission notice appear in all copies.
945ae9d61Sreyk  *
1045ae9d61Sreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1145ae9d61Sreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1245ae9d61Sreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1345ae9d61Sreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1445ae9d61Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1545ae9d61Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1645ae9d61Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1745ae9d61Sreyk  */
1845ae9d61Sreyk 
19d8ea035bSderaadt #include <sys/types.h>
2045ae9d61Sreyk #include <sys/queue.h>
2145ae9d61Sreyk #include <sys/socket.h>
2245ae9d61Sreyk #include <sys/uio.h>
2345ae9d61Sreyk 
2445ae9d61Sreyk #include <stdio.h>
2545ae9d61Sreyk #include <stdlib.h>
2645ae9d61Sreyk #include <unistd.h>
2745ae9d61Sreyk #include <string.h>
2845ae9d61Sreyk #include <errno.h>
2945ae9d61Sreyk #include <fcntl.h>
3045ae9d61Sreyk #include <event.h>
3145ae9d61Sreyk 
3208c24fddStobhe #include <openssl/ecdsa.h>
3345ae9d61Sreyk #include <openssl/hmac.h>
3445ae9d61Sreyk #include <openssl/evp.h>
3545ae9d61Sreyk #include <openssl/sha.h>
3645ae9d61Sreyk #include <openssl/md5.h>
3745ae9d61Sreyk #include <openssl/x509.h>
38a4194998Sjsg #include <openssl/rsa.h>
3945ae9d61Sreyk 
4045ae9d61Sreyk #include "iked.h"
4145ae9d61Sreyk #include "ikev2.h"
4245ae9d61Sreyk 
435e4d3a37Sreyk /* RFC 7427, A.1 RSA */
445e4d3a37Sreyk static const uint8_t sha256WithRSA[] = {
4548b975e3Smarkus 	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
4648b975e3Smarkus 	0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00
4748b975e3Smarkus };
485e4d3a37Sreyk static const uint8_t sha384WithRSA[] = {
4948b975e3Smarkus 	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
5048b975e3Smarkus 	0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00
5148b975e3Smarkus };
525e4d3a37Sreyk static const uint8_t sha512WithRSA[] = {
5348b975e3Smarkus 	0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
5448b975e3Smarkus 	0xf7, 0x0d, 0x01, 0x01, 0x0d, 0x05, 0x00
5548b975e3Smarkus };
565e4d3a37Sreyk /* RFC 7427, A.3 ECDSA */
575e4d3a37Sreyk static const uint8_t ecdsa_sha256[] = {
585e4d3a37Sreyk 	0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
595e4d3a37Sreyk 	0x3d, 0x04, 0x03, 0x02
605e4d3a37Sreyk };
615e4d3a37Sreyk static const uint8_t ecdsa_sha384[] = {
625e4d3a37Sreyk 	0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
635e4d3a37Sreyk 	0x3d, 0x04, 0x03, 0x03
645e4d3a37Sreyk };
655e4d3a37Sreyk static const uint8_t ecdsa_sha512[] = {
665e4d3a37Sreyk 	0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
675e4d3a37Sreyk 	0x3d, 0x04, 0x03, 0x04
685e4d3a37Sreyk };
69753a20acStobhe /* RFC 7427, A.4.3 RSASSA-PSS with SHA-256 */
70753a20acStobhe static const uint8_t rsapss_sha256[] = {
71753a20acStobhe 	0x30, 0x46, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
72753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x39, 0xa0,
73753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
74753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
75753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
76753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
77753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
78753a20acStobhe 	0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03,
79753a20acStobhe 	0x02, 0x01, 0x20, 0xa3, 0x03, 0x02, 0x01, 0x01
80753a20acStobhe };
81753a20acStobhe /* RSASSA-PSS SHA-384 */
82753a20acStobhe static const uint8_t rsapss_sha384[] = {
83753a20acStobhe 	0x30, 0x46, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
84753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,
85753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
86753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,
87753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
88753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
89753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
90753a20acStobhe 	0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03,
91753a20acStobhe 	0x02, 0x01, 0x30, 0xa3, 0x03, 0x02, 0x01, 0x01
92753a20acStobhe };
93753a20acStobhe /* RSASSA-PSS SHA-512 */
94753a20acStobhe static const uint8_t rsapss_sha512[] = {
95753a20acStobhe 	0x30, 0x46, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
96753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,
97753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
98753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00,
99753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
100753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
101753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
102753a20acStobhe 	0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03,
103753a20acStobhe 	0x02, 0x01, 0x40, 0xa3, 0x03, 0x02, 0x01, 0x01
104753a20acStobhe };
105753a20acStobhe /* RSASSA-PSS SHA-256, no trailer */
106753a20acStobhe static const uint8_t rsapss_sha256nt[] = {
107753a20acStobhe 	0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
108753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,
109753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
110753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00,
111753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
112753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
113753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
114753a20acStobhe 	0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xa2, 0x03,
115753a20acStobhe 	0x02, 0x01, 0x20
116753a20acStobhe };
117753a20acStobhe /* RSASSA-PSS SHA-384, no trailer */
118753a20acStobhe static const uint8_t rsapss_sha384nt[] = {
119753a20acStobhe 	0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
120753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,
121753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
122753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00,
123753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
124753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
125753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
126753a20acStobhe 	0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0xa2, 0x03,
127753a20acStobhe 	0x02, 0x01, 0x30
128753a20acStobhe };
129753a20acStobhe /* RSASSA-PSS SHA-512, no trailer */
130753a20acStobhe static const uint8_t rsapss_sha512nt[] = {
131753a20acStobhe 	0x30, 0x41, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
132753a20acStobhe 	0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x34, 0xa0,
133753a20acStobhe 	0x0f, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
134753a20acStobhe 	0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00,
135753a20acStobhe 	0xa1, 0x1c, 0x30, 0x1a, 0x06, 0x09, 0x2a, 0x86,
136753a20acStobhe 	0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30,
137753a20acStobhe 	0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65,
138753a20acStobhe 	0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0xa2, 0x03,
139753a20acStobhe 	0x02, 0x01, 0x40
140753a20acStobhe };
141753a20acStobhe 
142753a20acStobhe #define FLAG_RSA_PSS	0x00001
143466d2dbaStobhe int force_rsa_pss = 0;	/* XXX move to API */
14448b975e3Smarkus 
1455e4d3a37Sreyk static const struct {
1465e4d3a37Sreyk 	int		 sc_keytype;
1475e4d3a37Sreyk 	const EVP_MD	*(*sc_md)(void);
148d09d3a7dSreyk 	uint8_t		 sc_len;
149d09d3a7dSreyk 	const uint8_t	*sc_oid;
150753a20acStobhe 	uint32_t	 sc_flags;
15148b975e3Smarkus } schemes[] = {
152753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha256, sizeof(sha256WithRSA), sha256WithRSA, 0 },
153753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha384, sizeof(sha384WithRSA), sha384WithRSA, 0 },
154753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha512, sizeof(sha512WithRSA), sha512WithRSA, 0 },
155753a20acStobhe 	{ EVP_PKEY_EC,  EVP_sha256, sizeof(ecdsa_sha256),  ecdsa_sha256, 0 },
156753a20acStobhe 	{ EVP_PKEY_EC,  EVP_sha384, sizeof(ecdsa_sha384),  ecdsa_sha384, 0 },
157753a20acStobhe 	{ EVP_PKEY_EC,  EVP_sha512, sizeof(ecdsa_sha512),  ecdsa_sha512, 0 },
158753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha256, sizeof(rsapss_sha256), rsapss_sha256,
159753a20acStobhe 	    FLAG_RSA_PSS },
160753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha384, sizeof(rsapss_sha384), rsapss_sha384,
161753a20acStobhe 	    FLAG_RSA_PSS },
162753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha512, sizeof(rsapss_sha512), rsapss_sha512,
163753a20acStobhe 	    FLAG_RSA_PSS },
164753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha256, sizeof(rsapss_sha256nt), rsapss_sha256nt,
165753a20acStobhe 	    FLAG_RSA_PSS },
166753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha384, sizeof(rsapss_sha384nt), rsapss_sha384nt,
167753a20acStobhe 	    FLAG_RSA_PSS },
168753a20acStobhe 	{ EVP_PKEY_RSA, EVP_sha512, sizeof(rsapss_sha512nt), rsapss_sha512nt,
169753a20acStobhe 	    FLAG_RSA_PSS },
17048b975e3Smarkus };
17148b975e3Smarkus 
172466d2dbaStobhe int	_dsa_verify_init(struct iked_dsa *, const uint8_t *, size_t);
1735e4d3a37Sreyk int	_dsa_verify_prepare(struct iked_dsa *, uint8_t **, size_t *,
1745e4d3a37Sreyk 	    uint8_t **);
175cb2fef99Stobhe int	_dsa_sign_encode(struct iked_dsa *, uint8_t *, size_t, size_t *);
1765e4d3a37Sreyk int	_dsa_sign_ecdsa(struct iked_dsa *, uint8_t *, size_t);
17748b975e3Smarkus 
17845ae9d61Sreyk struct iked_hash *
179d09d3a7dSreyk hash_new(uint8_t type, uint16_t id)
18045ae9d61Sreyk {
18145ae9d61Sreyk 	struct iked_hash	*hash;
18245ae9d61Sreyk 	const EVP_MD		*md = NULL;
18315863c3aStobhe 	int			 length = 0, fixedkey = 0, trunc = 0, isaead = 0;
18445ae9d61Sreyk 
18545ae9d61Sreyk 	switch (type) {
18645ae9d61Sreyk 	case IKEV2_XFORMTYPE_PRF:
18745ae9d61Sreyk 		switch (id) {
18845ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_MD5:
18945ae9d61Sreyk 			md = EVP_md5();
19045ae9d61Sreyk 			length = MD5_DIGEST_LENGTH;
19145ae9d61Sreyk 			break;
19245ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_SHA1:
19345ae9d61Sreyk 			md = EVP_sha1();
19445ae9d61Sreyk 			length = SHA_DIGEST_LENGTH;
19545ae9d61Sreyk 			break;
19645ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_SHA2_256:
19745ae9d61Sreyk 			md = EVP_sha256();
19845ae9d61Sreyk 			length = SHA256_DIGEST_LENGTH;
19945ae9d61Sreyk 			break;
20045ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_SHA2_384:
20145ae9d61Sreyk 			md = EVP_sha384();
20245ae9d61Sreyk 			length = SHA384_DIGEST_LENGTH;
20345ae9d61Sreyk 			break;
20445ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_SHA2_512:
20545ae9d61Sreyk 			md = EVP_sha512();
20645ae9d61Sreyk 			length = SHA512_DIGEST_LENGTH;
20745ae9d61Sreyk 			break;
20845ae9d61Sreyk 		case IKEV2_XFORMPRF_AES128_XCBC:
20945ae9d61Sreyk 			fixedkey = 128 / 8;
21045ae9d61Sreyk 			length = fixedkey;
21145ae9d61Sreyk 			/* FALLTHROUGH */
21245ae9d61Sreyk 		case IKEV2_XFORMPRF_HMAC_TIGER:
21345ae9d61Sreyk 		case IKEV2_XFORMPRF_AES128_CMAC:
21445ae9d61Sreyk 		default:
2157eced9f4Smikeb 			log_debug("%s: prf %s not supported", __func__,
21645ae9d61Sreyk 			    print_map(id, ikev2_xformprf_map));
21745ae9d61Sreyk 			break;
21845ae9d61Sreyk 		}
21945ae9d61Sreyk 		break;
22045ae9d61Sreyk 	case IKEV2_XFORMTYPE_INTEGR:
22145ae9d61Sreyk 		switch (id) {
22245ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_MD5_96:
22345ae9d61Sreyk 			md = EVP_md5();
22445ae9d61Sreyk 			length = MD5_DIGEST_LENGTH;
22545ae9d61Sreyk 			trunc = 12;
22645ae9d61Sreyk 			break;
22745ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_SHA1_96:
22845ae9d61Sreyk 			md = EVP_sha1();
22945ae9d61Sreyk 			length = SHA_DIGEST_LENGTH;
23045ae9d61Sreyk 			trunc = 12;
23145ae9d61Sreyk 			break;
23245ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_SHA2_256_128:
23345ae9d61Sreyk 			md = EVP_sha256();
23445ae9d61Sreyk 			length = SHA256_DIGEST_LENGTH;
23545ae9d61Sreyk 			trunc = 16;
23645ae9d61Sreyk 			break;
23745ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_SHA2_384_192:
23845ae9d61Sreyk 			md = EVP_sha384();
23945ae9d61Sreyk 			length = SHA384_DIGEST_LENGTH;
24045ae9d61Sreyk 			trunc = 24;
24145ae9d61Sreyk 			break;
24245ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_SHA2_512_256:
24345ae9d61Sreyk 			md = EVP_sha512();
24445ae9d61Sreyk 			length = SHA512_DIGEST_LENGTH;
24545ae9d61Sreyk 			trunc = 32;
24645ae9d61Sreyk 			break;
24715863c3aStobhe 		case IKEV2_XFORMAUTH_AES_GCM_12:
24815863c3aStobhe 			length = 12;
24915863c3aStobhe 			isaead = 1;
25015863c3aStobhe 			break;
25115863c3aStobhe 		case IKEV2_XFORMAUTH_AES_GCM_16:
25215863c3aStobhe 			length = 16;
25315863c3aStobhe 			isaead = 1;
25415863c3aStobhe 			break;
25545ae9d61Sreyk 		case IKEV2_XFORMAUTH_NONE:
25645ae9d61Sreyk 		case IKEV2_XFORMAUTH_DES_MAC:
25745ae9d61Sreyk 		case IKEV2_XFORMAUTH_KPDK_MD5:
25845ae9d61Sreyk 		case IKEV2_XFORMAUTH_AES_XCBC_96:
25945ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_MD5_128:
26045ae9d61Sreyk 		case IKEV2_XFORMAUTH_HMAC_SHA1_160:
26145ae9d61Sreyk 		case IKEV2_XFORMAUTH_AES_CMAC_96:
26245ae9d61Sreyk 		case IKEV2_XFORMAUTH_AES_128_GMAC:
26345ae9d61Sreyk 		case IKEV2_XFORMAUTH_AES_192_GMAC:
26445ae9d61Sreyk 		case IKEV2_XFORMAUTH_AES_256_GMAC:
26545ae9d61Sreyk 		default:
2667eced9f4Smikeb 			log_debug("%s: auth %s not supported", __func__,
26745ae9d61Sreyk 			    print_map(id, ikev2_xformauth_map));
26845ae9d61Sreyk 			break;
26945ae9d61Sreyk 		}
27045ae9d61Sreyk 		break;
27145ae9d61Sreyk 	default:
2727eced9f4Smikeb 		log_debug("%s: hash type %s not supported", __func__,
27345ae9d61Sreyk 		    print_map(id, ikev2_xformtype_map));
27445ae9d61Sreyk 		break;
27545ae9d61Sreyk 	}
27615863c3aStobhe 	if (!isaead && md == NULL)
27745ae9d61Sreyk 		return (NULL);
27845ae9d61Sreyk 
27945ae9d61Sreyk 	if ((hash = calloc(1, sizeof(*hash))) == NULL) {
28045ae9d61Sreyk 		log_debug("%s: alloc hash", __func__);
28145ae9d61Sreyk 		return (NULL);
28245ae9d61Sreyk 	}
28345ae9d61Sreyk 
28445ae9d61Sreyk 	hash->hash_type = type;
28545ae9d61Sreyk 	hash->hash_id = id;
28645ae9d61Sreyk 	hash->hash_priv = md;
28745ae9d61Sreyk 	hash->hash_ctx = NULL;
28845ae9d61Sreyk 	hash->hash_trunc = trunc;
28945ae9d61Sreyk 	hash->hash_length = length;
29045ae9d61Sreyk 	hash->hash_fixedkey = fixedkey;
29115863c3aStobhe 	hash->hash_isaead = isaead;
29215863c3aStobhe 
29315863c3aStobhe 	if (isaead)
29415863c3aStobhe 		return (hash);
29545ae9d61Sreyk 
29608c24fddStobhe 	hash->hash_ctx = HMAC_CTX_new();
29708c24fddStobhe 	if (hash->hash_ctx == NULL) {
29845ae9d61Sreyk 		log_debug("%s: alloc hash ctx", __func__);
29945ae9d61Sreyk 		hash_free(hash);
30045ae9d61Sreyk 		return (NULL);
30145ae9d61Sreyk 	}
30245ae9d61Sreyk 
30345ae9d61Sreyk 	return (hash);
30445ae9d61Sreyk }
30545ae9d61Sreyk 
30645ae9d61Sreyk struct ibuf *
30745ae9d61Sreyk hash_setkey(struct iked_hash *hash, void *key, size_t keylen)
30845ae9d61Sreyk {
309be2b38f5Sclaudio 	ibuf_free(hash->hash_key);
31045ae9d61Sreyk 	if ((hash->hash_key = ibuf_new(key, keylen)) == NULL) {
31145ae9d61Sreyk 		log_debug("%s: alloc hash key", __func__);
31245ae9d61Sreyk 		return (NULL);
31345ae9d61Sreyk 	}
31445ae9d61Sreyk 	return (hash->hash_key);
31545ae9d61Sreyk }
31645ae9d61Sreyk 
31745ae9d61Sreyk void
31845ae9d61Sreyk hash_free(struct iked_hash *hash)
31945ae9d61Sreyk {
32045ae9d61Sreyk 	if (hash == NULL)
32145ae9d61Sreyk 		return;
32208c24fddStobhe 	HMAC_CTX_free(hash->hash_ctx);
323be2b38f5Sclaudio 	ibuf_free(hash->hash_key);
32445ae9d61Sreyk 	free(hash);
32545ae9d61Sreyk }
32645ae9d61Sreyk 
32745ae9d61Sreyk void
32845ae9d61Sreyk hash_init(struct iked_hash *hash)
32945ae9d61Sreyk {
330a699afcaSclaudio 	HMAC_Init_ex(hash->hash_ctx, ibuf_data(hash->hash_key),
331eef6c82aSclaudio 	    ibuf_size(hash->hash_key), hash->hash_priv, NULL);
33245ae9d61Sreyk }
33345ae9d61Sreyk 
33445ae9d61Sreyk void
33545ae9d61Sreyk hash_update(struct iked_hash *hash, void *buf, size_t len)
33645ae9d61Sreyk {
33745ae9d61Sreyk 	HMAC_Update(hash->hash_ctx, buf, len);
33845ae9d61Sreyk }
33945ae9d61Sreyk 
34045ae9d61Sreyk void
34145ae9d61Sreyk hash_final(struct iked_hash *hash, void *buf, size_t *len)
34245ae9d61Sreyk {
343d09d3a7dSreyk 	unsigned int	 length = 0;
34445ae9d61Sreyk 
34545ae9d61Sreyk 	HMAC_Final(hash->hash_ctx, buf, &length);
34645ae9d61Sreyk 	*len = (size_t)length;
34745ae9d61Sreyk 
34845ae9d61Sreyk 	/* Truncate the result if required by the alg */
34945ae9d61Sreyk 	if (hash->hash_trunc && *len > hash->hash_trunc)
35045ae9d61Sreyk 		*len = hash->hash_trunc;
35145ae9d61Sreyk }
35245ae9d61Sreyk 
35345ae9d61Sreyk size_t
35445ae9d61Sreyk hash_length(struct iked_hash *hash)
35545ae9d61Sreyk {
35645ae9d61Sreyk 	if (hash->hash_trunc)
35745ae9d61Sreyk 		return (hash->hash_trunc);
35845ae9d61Sreyk 	return (hash->hash_length);
35945ae9d61Sreyk }
36045ae9d61Sreyk 
36145ae9d61Sreyk size_t
36245ae9d61Sreyk hash_keylength(struct iked_hash *hash)
36345ae9d61Sreyk {
36445ae9d61Sreyk 	return (hash->hash_length);
36545ae9d61Sreyk }
36645ae9d61Sreyk 
36745ae9d61Sreyk struct iked_cipher *
368d09d3a7dSreyk cipher_new(uint8_t type, uint16_t id, uint16_t id_length)
36945ae9d61Sreyk {
37045ae9d61Sreyk 	struct iked_cipher	*encr;
37145ae9d61Sreyk 	const EVP_CIPHER	*cipher = NULL;
37245ae9d61Sreyk 	int			 length = 0, fixedkey = 0, ivlength = 0;
37315863c3aStobhe 	int			 saltlength = 0, authid = 0;
37445ae9d61Sreyk 
37545ae9d61Sreyk 	switch (type) {
37645ae9d61Sreyk 	case IKEV2_XFORMTYPE_ENCR:
37745ae9d61Sreyk 		switch (id) {
37845ae9d61Sreyk 		case IKEV2_XFORMENCR_3DES:
37945ae9d61Sreyk 			cipher = EVP_des_ede3_cbc();
38045ae9d61Sreyk 			length = EVP_CIPHER_block_size(cipher);
38145ae9d61Sreyk 			fixedkey = EVP_CIPHER_key_length(cipher);
38245ae9d61Sreyk 			ivlength = EVP_CIPHER_iv_length(cipher);
38345ae9d61Sreyk 			break;
38445ae9d61Sreyk 		case IKEV2_XFORMENCR_AES_CBC:
38545ae9d61Sreyk 			switch (id_length) {
38645ae9d61Sreyk 			case 128:
38745ae9d61Sreyk 				cipher = EVP_aes_128_cbc();
38845ae9d61Sreyk 				break;
38945ae9d61Sreyk 			case 192:
39045ae9d61Sreyk 				cipher = EVP_aes_192_cbc();
39145ae9d61Sreyk 				break;
39245ae9d61Sreyk 			case 256:
39345ae9d61Sreyk 				cipher = EVP_aes_256_cbc();
39445ae9d61Sreyk 				break;
39545ae9d61Sreyk 			default:
39645ae9d61Sreyk 				log_debug("%s: invalid key length %d"
39745ae9d61Sreyk 				    " for cipher %s", __func__, id_length,
39845ae9d61Sreyk 				    print_map(id, ikev2_xformencr_map));
39945ae9d61Sreyk 				break;
40045ae9d61Sreyk 			}
40145ae9d61Sreyk 			if (cipher == NULL)
40245ae9d61Sreyk 				break;
403953685aaSreyk 			length = EVP_CIPHER_block_size(cipher);
40445ae9d61Sreyk 			ivlength = EVP_CIPHER_iv_length(cipher);
40545ae9d61Sreyk 			fixedkey = EVP_CIPHER_key_length(cipher);
40645ae9d61Sreyk 			break;
40715863c3aStobhe 		case IKEV2_XFORMENCR_AES_GCM_16:
40815863c3aStobhe 		case IKEV2_XFORMENCR_AES_GCM_12:
40915863c3aStobhe 			switch (id_length) {
41015863c3aStobhe 			case 128:
41115863c3aStobhe 				cipher = EVP_aes_128_gcm();
41215863c3aStobhe 				break;
41315863c3aStobhe 			case 256:
41415863c3aStobhe 				cipher = EVP_aes_256_gcm();
41515863c3aStobhe 				break;
41615863c3aStobhe 			default:
41715863c3aStobhe 				log_debug("%s: invalid key length %d"
41815863c3aStobhe 				    " for cipher %s", __func__, id_length,
41915863c3aStobhe 				    print_map(id, ikev2_xformencr_map));
42015863c3aStobhe 				break;
42115863c3aStobhe 			}
42215863c3aStobhe 			if (cipher == NULL)
42315863c3aStobhe 				break;
42415863c3aStobhe 			switch(id) {
42515863c3aStobhe 			case IKEV2_XFORMENCR_AES_GCM_16:
42615863c3aStobhe 				authid = IKEV2_XFORMAUTH_AES_GCM_16;
42715863c3aStobhe 				break;
42815863c3aStobhe 			case IKEV2_XFORMENCR_AES_GCM_12:
42915863c3aStobhe 				authid = IKEV2_XFORMAUTH_AES_GCM_12;
43015863c3aStobhe 				break;
43115863c3aStobhe 			}
43215863c3aStobhe 			length = EVP_CIPHER_block_size(cipher);
43315863c3aStobhe 			ivlength = 8;
43415863c3aStobhe 			saltlength = 4;
43515863c3aStobhe 			fixedkey = EVP_CIPHER_key_length(cipher) + saltlength;
43615863c3aStobhe 			break;
43745ae9d61Sreyk 		case IKEV2_XFORMENCR_DES_IV64:
43845ae9d61Sreyk 		case IKEV2_XFORMENCR_DES:
43945ae9d61Sreyk 		case IKEV2_XFORMENCR_RC5:
44045ae9d61Sreyk 		case IKEV2_XFORMENCR_IDEA:
44145ae9d61Sreyk 		case IKEV2_XFORMENCR_CAST:
44245ae9d61Sreyk 		case IKEV2_XFORMENCR_BLOWFISH:
44345ae9d61Sreyk 		case IKEV2_XFORMENCR_3IDEA:
44445ae9d61Sreyk 		case IKEV2_XFORMENCR_DES_IV32:
44545ae9d61Sreyk 		case IKEV2_XFORMENCR_NULL:
44645ae9d61Sreyk 		case IKEV2_XFORMENCR_AES_CTR:
44745ae9d61Sreyk 			/* FALLTHROUGH */
44845ae9d61Sreyk 		default:
4497eced9f4Smikeb 			log_debug("%s: cipher %s not supported", __func__,
45045ae9d61Sreyk 			    print_map(id, ikev2_xformencr_map));
45145ae9d61Sreyk 			cipher = NULL;
45245ae9d61Sreyk 			break;
45345ae9d61Sreyk 		}
45445ae9d61Sreyk 		break;
45545ae9d61Sreyk 	default:
4567eced9f4Smikeb 		log_debug("%s: cipher type %s not supported", __func__,
45745ae9d61Sreyk 		    print_map(id, ikev2_xformtype_map));
45845ae9d61Sreyk 		break;
45945ae9d61Sreyk 	}
46045ae9d61Sreyk 	if (cipher == NULL)
46145ae9d61Sreyk 		return (NULL);
46245ae9d61Sreyk 
46345ae9d61Sreyk 	if ((encr = calloc(1, sizeof(*encr))) == NULL) {
46445ae9d61Sreyk 		log_debug("%s: alloc cipher", __func__);
46545ae9d61Sreyk 		return (NULL);
46645ae9d61Sreyk 	}
46745ae9d61Sreyk 
46845ae9d61Sreyk 	encr->encr_id = id;
46945ae9d61Sreyk 	encr->encr_priv = cipher;
47045ae9d61Sreyk 	encr->encr_ctx = NULL;
47145ae9d61Sreyk 	encr->encr_length = length;
47245ae9d61Sreyk 	encr->encr_fixedkey = fixedkey;
47345ae9d61Sreyk 	encr->encr_ivlength = ivlength ? ivlength : length;
47415863c3aStobhe 	encr->encr_saltlength = saltlength;
47515863c3aStobhe 	encr->encr_authid = authid;
47645ae9d61Sreyk 
47708c24fddStobhe 	encr->encr_ctx = EVP_CIPHER_CTX_new();
47808c24fddStobhe 	if (encr->encr_ctx == NULL) {
47945ae9d61Sreyk 		log_debug("%s: alloc cipher ctx", __func__);
48045ae9d61Sreyk 		cipher_free(encr);
48145ae9d61Sreyk 		return (NULL);
48245ae9d61Sreyk 	}
48345ae9d61Sreyk 
48445ae9d61Sreyk 	return (encr);
48545ae9d61Sreyk }
48645ae9d61Sreyk 
48745ae9d61Sreyk struct ibuf *
488a9a2a639Stobhe cipher_setkey(struct iked_cipher *encr, const void *key, size_t keylen)
48945ae9d61Sreyk {
490be2b38f5Sclaudio 	ibuf_free(encr->encr_key);
49145ae9d61Sreyk 	if ((encr->encr_key = ibuf_new(key, keylen)) == NULL) {
49245ae9d61Sreyk 		log_debug("%s: alloc cipher key", __func__);
49345ae9d61Sreyk 		return (NULL);
49445ae9d61Sreyk 	}
49545ae9d61Sreyk 	return (encr->encr_key);
49645ae9d61Sreyk }
49745ae9d61Sreyk 
49845ae9d61Sreyk struct ibuf *
499a9a2a639Stobhe cipher_setiv(struct iked_cipher *encr, const void *iv, size_t len)
50045ae9d61Sreyk {
501be2b38f5Sclaudio 	ibuf_free(encr->encr_iv);
5025e4d3a37Sreyk 	encr->encr_iv = NULL;
50345ae9d61Sreyk 	if (iv != NULL) {
50445ae9d61Sreyk 		if (len < encr->encr_ivlength) {
505328746baSreyk 			log_debug("%s: invalid IV length %zu", __func__, len);
50645ae9d61Sreyk 			return (NULL);
50745ae9d61Sreyk 		}
50845ae9d61Sreyk 		encr->encr_iv = ibuf_new(iv, encr->encr_ivlength);
50945ae9d61Sreyk 	} else {
510c4530a33Stobhe 		switch (encr->encr_id) {
511c4530a33Stobhe 		case IKEV2_XFORMENCR_AES_GCM_16:
512c4530a33Stobhe 		case IKEV2_XFORMENCR_AES_GCM_12:
513c4530a33Stobhe 			if (encr->encr_ivlength != sizeof(encr->encr_civ)) {
514c4530a33Stobhe 				log_info("%s: ivlen does not match %zu != %zu",
515c4530a33Stobhe 				    __func__, encr->encr_ivlength,
516c4530a33Stobhe 				    sizeof(encr->encr_civ));
517c4530a33Stobhe 				return (NULL);
518c4530a33Stobhe 			}
519c4530a33Stobhe 			encr->encr_iv = ibuf_new(&encr->encr_civ, sizeof(encr->encr_civ));
520c4530a33Stobhe 			encr->encr_civ++;
521c4530a33Stobhe 			break;
522c4530a33Stobhe 		default:
52345ae9d61Sreyk 			/* Get new random IV */
52445ae9d61Sreyk 			encr->encr_iv = ibuf_random(encr->encr_ivlength);
52545ae9d61Sreyk 		}
526c4530a33Stobhe 	}
52745ae9d61Sreyk 	if (encr->encr_iv == NULL) {
52845ae9d61Sreyk 		log_debug("%s: failed to set IV", __func__);
52945ae9d61Sreyk 		return (NULL);
53045ae9d61Sreyk 	}
53145ae9d61Sreyk 	return (encr->encr_iv);
53245ae9d61Sreyk }
53345ae9d61Sreyk 
53415863c3aStobhe int
53515863c3aStobhe cipher_settag(struct iked_cipher *encr, uint8_t *data, size_t len)
53615863c3aStobhe {
53715863c3aStobhe 	return (EVP_CIPHER_CTX_ctrl(encr->encr_ctx,
53815863c3aStobhe 	    EVP_CTRL_GCM_SET_TAG, len, data) != 1);
53915863c3aStobhe }
54015863c3aStobhe 
54115863c3aStobhe int
54215863c3aStobhe cipher_gettag(struct iked_cipher *encr, uint8_t *data, size_t len)
54315863c3aStobhe {
54415863c3aStobhe 	return (EVP_CIPHER_CTX_ctrl(encr->encr_ctx,
54515863c3aStobhe 	    EVP_CTRL_GCM_GET_TAG, len, data) != 1);
54615863c3aStobhe }
54715863c3aStobhe 
54845ae9d61Sreyk void
54945ae9d61Sreyk cipher_free(struct iked_cipher *encr)
55045ae9d61Sreyk {
55145ae9d61Sreyk 	if (encr == NULL)
55245ae9d61Sreyk 		return;
553422a8d39Stb 	EVP_CIPHER_CTX_free(encr->encr_ctx);
554be2b38f5Sclaudio 	ibuf_free(encr->encr_iv);
555be2b38f5Sclaudio 	ibuf_free(encr->encr_key);
55645ae9d61Sreyk 	free(encr);
55745ae9d61Sreyk }
55845ae9d61Sreyk 
55981b8fecaStobhe int
56045ae9d61Sreyk cipher_init(struct iked_cipher *encr, int enc)
56145ae9d61Sreyk {
56215863c3aStobhe 	struct ibuf	*nonce = NULL;
56315863c3aStobhe 	int		 ret = -1;
56415863c3aStobhe 
56581b8fecaStobhe 	if (EVP_CipherInit_ex(encr->encr_ctx, encr->encr_priv, NULL,
56615863c3aStobhe 	    NULL, NULL, enc) != 1)
56715863c3aStobhe 		return (-1);
56815863c3aStobhe 	if (encr->encr_saltlength > 0) {
56915863c3aStobhe 		/* For AEADs the nonce is salt + IV  (see RFC5282) */
5705001b11bSclaudio 		nonce = ibuf_new(ibuf_seek(encr->encr_key,
57115863c3aStobhe 		    ibuf_size(encr->encr_key) - encr->encr_saltlength,
5725001b11bSclaudio 		    encr->encr_saltlength), encr->encr_saltlength);
57315863c3aStobhe 		if (nonce == NULL)
57415863c3aStobhe 			return (-1);
575*fa353a8fSclaudio 		if (ibuf_add_ibuf(nonce, encr->encr_iv) != 0)
57615863c3aStobhe 			goto done;
57715863c3aStobhe 		if (EVP_CipherInit_ex(encr->encr_ctx, NULL, NULL,
57815863c3aStobhe 		    ibuf_data(encr->encr_key), ibuf_data(nonce), enc) != 1)
57915863c3aStobhe 			goto done;
58015863c3aStobhe 	} else
58115863c3aStobhe 		if (EVP_CipherInit_ex(encr->encr_ctx, NULL, NULL,
58281b8fecaStobhe 		    ibuf_data(encr->encr_key), ibuf_data(encr->encr_iv), enc) != 1)
58381b8fecaStobhe 			return (-1);
5843189733aSmikeb 	EVP_CIPHER_CTX_set_padding(encr->encr_ctx, 0);
58515863c3aStobhe 	ret = 0;
58615863c3aStobhe  done:
58715863c3aStobhe 	ibuf_free(nonce);
58815863c3aStobhe 	return (ret);
58945ae9d61Sreyk }
59045ae9d61Sreyk 
59181b8fecaStobhe int
59245ae9d61Sreyk cipher_init_encrypt(struct iked_cipher *encr)
59345ae9d61Sreyk {
59481b8fecaStobhe 	return (cipher_init(encr, 1));
59545ae9d61Sreyk }
59645ae9d61Sreyk 
59781b8fecaStobhe int
59845ae9d61Sreyk cipher_init_decrypt(struct iked_cipher *encr)
59945ae9d61Sreyk {
60081b8fecaStobhe 	return (cipher_init(encr, 0));
60145ae9d61Sreyk }
60245ae9d61Sreyk 
60315863c3aStobhe void
604a9a2a639Stobhe cipher_aad(struct iked_cipher *encr, const void *in, size_t inlen,
60515863c3aStobhe     size_t *outlen)
60615863c3aStobhe {
60715863c3aStobhe 	int	 olen = 0;
60815863c3aStobhe 
60915863c3aStobhe 	if (EVP_CipherUpdate(encr->encr_ctx, NULL, &olen, in, inlen) != 1) {
61015863c3aStobhe 		ca_sslerror(__func__);
61115863c3aStobhe 		*outlen = 0;
61215863c3aStobhe 		return;
61315863c3aStobhe 	}
61415863c3aStobhe 	*outlen = (size_t)olen;
61515863c3aStobhe }
61615863c3aStobhe 
61781b8fecaStobhe int
618a9a2a639Stobhe cipher_update(struct iked_cipher *encr, const void *in, size_t inlen,
61945ae9d61Sreyk     void *out, size_t *outlen)
62045ae9d61Sreyk {
62145ae9d61Sreyk 	int	 olen;
62245ae9d61Sreyk 
62345ae9d61Sreyk 	olen = 0;
62481b8fecaStobhe 	if (EVP_CipherUpdate(encr->encr_ctx, out, &olen, in, inlen) != 1) {
62586cf9d9cSmarkus 		ca_sslerror(__func__);
6263189733aSmikeb 		*outlen = 0;
62781b8fecaStobhe 		return (-1);
6283189733aSmikeb 	}
62945ae9d61Sreyk 	*outlen = (size_t)olen;
63081b8fecaStobhe 	return (0);
63145ae9d61Sreyk }
63245ae9d61Sreyk 
63381b8fecaStobhe int
63481b8fecaStobhe cipher_final(struct iked_cipher *encr)
63545ae9d61Sreyk {
63645ae9d61Sreyk 	int	 olen;
63745ae9d61Sreyk 
63881b8fecaStobhe 	/*
63981b8fecaStobhe 	 * We always have EVP_CIPH_NO_PADDING set.  This means arg
64081b8fecaStobhe 	 * out is not used and olen should always be 0.
64181b8fecaStobhe 	 */
64281b8fecaStobhe 	if (EVP_CipherFinal_ex(encr->encr_ctx, NULL, &olen) != 1) {
64386cf9d9cSmarkus 		ca_sslerror(__func__);
64481b8fecaStobhe 		return (-1);
64545ae9d61Sreyk 	}
64681b8fecaStobhe 	return (0);
64745ae9d61Sreyk }
64845ae9d61Sreyk 
64945ae9d61Sreyk size_t
65045ae9d61Sreyk cipher_length(struct iked_cipher *encr)
65145ae9d61Sreyk {
65245ae9d61Sreyk 	return (encr->encr_length);
65345ae9d61Sreyk }
65445ae9d61Sreyk 
65545ae9d61Sreyk size_t
65645ae9d61Sreyk cipher_keylength(struct iked_cipher *encr)
65745ae9d61Sreyk {
65845ae9d61Sreyk 	if (encr->encr_fixedkey)
65945ae9d61Sreyk 		return (encr->encr_fixedkey);
66045ae9d61Sreyk 
66145ae9d61Sreyk 	/* Might return zero */
66245ae9d61Sreyk 	return (ibuf_length(encr->encr_key));
66345ae9d61Sreyk }
66445ae9d61Sreyk 
66545ae9d61Sreyk size_t
66645ae9d61Sreyk cipher_ivlength(struct iked_cipher *encr)
66745ae9d61Sreyk {
66845ae9d61Sreyk 	return (encr->encr_ivlength);
66945ae9d61Sreyk }
67045ae9d61Sreyk 
67145ae9d61Sreyk size_t
67245ae9d61Sreyk cipher_outlength(struct iked_cipher *encr, size_t inlen)
67345ae9d61Sreyk {
674d5cae38cSmikeb 	return (roundup(inlen, encr->encr_length));
67545ae9d61Sreyk }
67645ae9d61Sreyk 
67745ae9d61Sreyk struct iked_dsa *
6786368155eStobhe dsa_new(uint8_t id, struct iked_hash *prf, int sign)
67945ae9d61Sreyk {
68045ae9d61Sreyk 	struct iked_dsa		*dsap = NULL, dsa;
68145ae9d61Sreyk 
68245ae9d61Sreyk 	bzero(&dsa, sizeof(dsa));
68345ae9d61Sreyk 
68445ae9d61Sreyk 	switch (id) {
68548b975e3Smarkus 	case IKEV2_AUTH_SIG:
68648b975e3Smarkus 		if (sign)
68748b975e3Smarkus 			dsa.dsa_priv = EVP_sha256(); /* XXX should be passed */
68848b975e3Smarkus 		else
68948b975e3Smarkus 			dsa.dsa_priv = NULL; /* set later by dsa_init() */
69048b975e3Smarkus 		break;
69145ae9d61Sreyk 	case IKEV2_AUTH_RSA_SIG:
692ab77649aSmikeb 		/* RFC5996 says we SHOULD use SHA1 here */
693ab77649aSmikeb 		dsa.dsa_priv = EVP_sha1();
69445ae9d61Sreyk 		break;
69545ae9d61Sreyk 	case IKEV2_AUTH_SHARED_KEY_MIC:
69645ae9d61Sreyk 		if (prf == NULL || prf->hash_priv == NULL)
69745ae9d61Sreyk 			fatalx("dsa_new: invalid PRF");
69845ae9d61Sreyk 		dsa.dsa_priv = prf->hash_priv;
69945ae9d61Sreyk 		dsa.dsa_hmac = 1;
70045ae9d61Sreyk 		break;
70145ae9d61Sreyk 	case IKEV2_AUTH_DSS_SIG:
70208c24fddStobhe 		dsa.dsa_priv = EVP_sha1();
70345ae9d61Sreyk 		break;
70445ae9d61Sreyk 	case IKEV2_AUTH_ECDSA_256:
70545ae9d61Sreyk 		dsa.dsa_priv = EVP_sha256();
70645ae9d61Sreyk 		break;
70745ae9d61Sreyk 	case IKEV2_AUTH_ECDSA_384:
70845ae9d61Sreyk 		dsa.dsa_priv = EVP_sha384();
70945ae9d61Sreyk 		break;
710ada108cbSnaddy 	case IKEV2_AUTH_ECDSA_521:
71145ae9d61Sreyk 		dsa.dsa_priv = EVP_sha512();
71245ae9d61Sreyk 		break;
71345ae9d61Sreyk 	default:
7147eced9f4Smikeb 		log_debug("%s: auth method %s not supported", __func__,
71545ae9d61Sreyk 		    print_map(id, ikev2_auth_map));
71645ae9d61Sreyk 		break;
71745ae9d61Sreyk 	}
71845ae9d61Sreyk 
71945ae9d61Sreyk 	if ((dsap = calloc(1, sizeof(*dsap))) == NULL) {
72045ae9d61Sreyk 		log_debug("%s: alloc dsa ctx", __func__);
72145ae9d61Sreyk 
72245ae9d61Sreyk 		return (NULL);
72345ae9d61Sreyk 	}
72445ae9d61Sreyk 	memcpy(dsap, &dsa, sizeof(*dsap));
72545ae9d61Sreyk 
72645ae9d61Sreyk 	dsap->dsa_method = id;
72745ae9d61Sreyk 	dsap->dsa_sign = sign;
72845ae9d61Sreyk 
72945ae9d61Sreyk 	if (dsap->dsa_hmac) {
73008c24fddStobhe 		if ((dsap->dsa_ctx = HMAC_CTX_new()) == NULL) {
73145ae9d61Sreyk 			log_debug("%s: alloc hash ctx", __func__);
73245ae9d61Sreyk 			dsa_free(dsap);
73345ae9d61Sreyk 			return (NULL);
73445ae9d61Sreyk 		}
73545ae9d61Sreyk 	} else {
73645ae9d61Sreyk 		if ((dsap->dsa_ctx = EVP_MD_CTX_create()) == NULL) {
73745ae9d61Sreyk 			log_debug("%s: alloc digest ctx", __func__);
73845ae9d61Sreyk 			dsa_free(dsap);
73945ae9d61Sreyk 			return (NULL);
74045ae9d61Sreyk 		}
74145ae9d61Sreyk 	}
74245ae9d61Sreyk 
74345ae9d61Sreyk 	return (dsap);
74445ae9d61Sreyk }
74545ae9d61Sreyk 
74645ae9d61Sreyk struct iked_dsa *
7476368155eStobhe dsa_sign_new(uint8_t id, struct iked_hash *prf)
74845ae9d61Sreyk {
74945ae9d61Sreyk 	return (dsa_new(id, prf, 1));
75045ae9d61Sreyk }
75145ae9d61Sreyk 
75245ae9d61Sreyk struct iked_dsa *
7536368155eStobhe dsa_verify_new(uint8_t id, struct iked_hash *prf)
75445ae9d61Sreyk {
75545ae9d61Sreyk 	return (dsa_new(id, prf, 0));
75645ae9d61Sreyk }
75745ae9d61Sreyk 
75845ae9d61Sreyk void
75945ae9d61Sreyk dsa_free(struct iked_dsa *dsa)
76045ae9d61Sreyk {
76145ae9d61Sreyk 	if (dsa == NULL)
76245ae9d61Sreyk 		return;
76345ae9d61Sreyk 	if (dsa->dsa_hmac) {
76408c24fddStobhe 		HMAC_CTX_free((HMAC_CTX *)dsa->dsa_ctx);
76545ae9d61Sreyk 	} else {
7667199b42cStobhe 		EVP_MD_CTX_free((EVP_MD_CTX *)dsa->dsa_ctx);
76745ae9d61Sreyk 		EVP_PKEY_free(dsa->dsa_key);
76845ae9d61Sreyk 	}
76945ae9d61Sreyk 
770be2b38f5Sclaudio 	ibuf_free(dsa->dsa_keydata);
77164449014Sreyk 	free(dsa);
77245ae9d61Sreyk }
77345ae9d61Sreyk 
77445ae9d61Sreyk struct ibuf *
775d09d3a7dSreyk dsa_setkey(struct iked_dsa *dsa, void *key, size_t keylen, uint8_t type)
77645ae9d61Sreyk {
77745ae9d61Sreyk 	BIO		*rawcert = NULL;
77845ae9d61Sreyk 	X509		*cert = NULL;
77945ae9d61Sreyk 	RSA		*rsa = NULL;
7805e4d3a37Sreyk 	EC_KEY		*ec = NULL;
78145ae9d61Sreyk 	EVP_PKEY	*pkey = NULL;
78245ae9d61Sreyk 
783be2b38f5Sclaudio 	ibuf_free(dsa->dsa_keydata);
78445ae9d61Sreyk 	if ((dsa->dsa_keydata = ibuf_new(key, keylen)) == NULL) {
78545ae9d61Sreyk 		log_debug("%s: alloc signature key", __func__);
78645ae9d61Sreyk 		return (NULL);
78745ae9d61Sreyk 	}
78845ae9d61Sreyk 
78945ae9d61Sreyk 	if ((rawcert = BIO_new_mem_buf(key, keylen)) == NULL)
79045ae9d61Sreyk 		goto err;
79145ae9d61Sreyk 
79245ae9d61Sreyk 	switch (type) {
79345ae9d61Sreyk 	case IKEV2_CERT_X509_CERT:
79445ae9d61Sreyk 		if ((cert = d2i_X509_bio(rawcert, NULL)) == NULL)
79545ae9d61Sreyk 			goto sslerr;
79645ae9d61Sreyk 		if ((pkey = X509_get_pubkey(cert)) == NULL)
79745ae9d61Sreyk 			goto sslerr;
79845ae9d61Sreyk 		dsa->dsa_key = pkey;
79945ae9d61Sreyk 		break;
80045ae9d61Sreyk 	case IKEV2_CERT_RSA_KEY:
80145ae9d61Sreyk 		if (dsa->dsa_sign) {
80245ae9d61Sreyk 			if ((rsa = d2i_RSAPrivateKey_bio(rawcert,
80345ae9d61Sreyk 			    NULL)) == NULL)
80445ae9d61Sreyk 				goto sslerr;
80545ae9d61Sreyk 		} else {
80645ae9d61Sreyk 			if ((rsa = d2i_RSAPublicKey_bio(rawcert,
80745ae9d61Sreyk 			    NULL)) == NULL)
80845ae9d61Sreyk 				goto sslerr;
80945ae9d61Sreyk 		}
81045ae9d61Sreyk 
81145ae9d61Sreyk 		if ((pkey = EVP_PKEY_new()) == NULL)
81245ae9d61Sreyk 			goto sslerr;
81345ae9d61Sreyk 		if (!EVP_PKEY_set1_RSA(pkey, rsa))
81445ae9d61Sreyk 			goto sslerr;
81545ae9d61Sreyk 
81664660e80Smarkus 		RSA_free(rsa);		/* pkey now has the reference */
81745ae9d61Sreyk 		dsa->dsa_key = pkey;
81845ae9d61Sreyk 		break;
8195e4d3a37Sreyk 	case IKEV2_CERT_ECDSA:
8205e4d3a37Sreyk 		if (dsa->dsa_sign) {
8215e4d3a37Sreyk 			if ((ec = d2i_ECPrivateKey_bio(rawcert, NULL)) == NULL)
8225e4d3a37Sreyk 				goto sslerr;
8235e4d3a37Sreyk 		} else {
8245e4d3a37Sreyk 			if ((ec = d2i_EC_PUBKEY_bio(rawcert, NULL)) == NULL)
8255e4d3a37Sreyk 				goto sslerr;
8265e4d3a37Sreyk 		}
8275e4d3a37Sreyk 
8285e4d3a37Sreyk 		if ((pkey = EVP_PKEY_new()) == NULL)
8295e4d3a37Sreyk 			goto sslerr;
8305e4d3a37Sreyk 		if (!EVP_PKEY_set1_EC_KEY(pkey, ec))
8315e4d3a37Sreyk 			goto sslerr;
8325e4d3a37Sreyk 
8335e4d3a37Sreyk 		EC_KEY_free(ec);	/* pkey now has the reference */
8345e4d3a37Sreyk 		dsa->dsa_key = pkey;
8355e4d3a37Sreyk 		break;
83645ae9d61Sreyk 	default:
83745ae9d61Sreyk 		if (dsa->dsa_hmac)
83845ae9d61Sreyk 			break;
83945ae9d61Sreyk 		log_debug("%s: unsupported key type", __func__);
84045ae9d61Sreyk 		goto err;
84145ae9d61Sreyk 	}
84245ae9d61Sreyk 
8437e0422b2Stobhe 	X509_free(cert);
8447e0422b2Stobhe 	BIO_free(rawcert);	/* temporary for parsing */
8457e0422b2Stobhe 
84645ae9d61Sreyk 	return (dsa->dsa_keydata);
84745ae9d61Sreyk 
84845ae9d61Sreyk  sslerr:
84986cf9d9cSmarkus 	ca_sslerror(__func__);
85045ae9d61Sreyk  err:
85145ae9d61Sreyk 	log_debug("%s: error", __func__);
85245ae9d61Sreyk 
85345ae9d61Sreyk 	RSA_free(rsa);
8545e4d3a37Sreyk 	EC_KEY_free(ec);
85545ae9d61Sreyk 	EVP_PKEY_free(pkey);
85645ae9d61Sreyk 	X509_free(cert);
85745ae9d61Sreyk 	BIO_free(rawcert);
858be2b38f5Sclaudio 	ibuf_free(dsa->dsa_keydata);
8595e4d3a37Sreyk 	dsa->dsa_keydata = NULL;
86045ae9d61Sreyk 	return (NULL);
86145ae9d61Sreyk }
86245ae9d61Sreyk 
86345ae9d61Sreyk int
864466d2dbaStobhe _dsa_verify_init(struct iked_dsa *dsa, const uint8_t *sig, size_t len)
86548b975e3Smarkus {
866d09d3a7dSreyk 	uint8_t			 oidlen;
86748b975e3Smarkus 	size_t			 i;
8685e4d3a37Sreyk 	int			 keytype;
86948b975e3Smarkus 
87048b975e3Smarkus 	if (dsa->dsa_priv != NULL)
87148b975e3Smarkus 		return (0);
87248b975e3Smarkus 	/*
87348b975e3Smarkus 	 * For IKEV2_AUTH_SIG the oid of the authentication signature
87448b975e3Smarkus 	 * is encoded in the first bytes of the auth message.
87548b975e3Smarkus 	 */
87648b975e3Smarkus 	if (dsa->dsa_method != IKEV2_AUTH_SIG)  {
87748b975e3Smarkus 		log_debug("%s: dsa_priv not set for %s", __func__,
87848b975e3Smarkus 		    print_map(dsa->dsa_method, ikev2_auth_map));
87948b975e3Smarkus 		return (-1);
88048b975e3Smarkus 	}
8815e4d3a37Sreyk 	if (dsa->dsa_key == NULL) {
8825e4d3a37Sreyk 		log_debug("%s: dsa_key not set for %s", __func__,
8835e4d3a37Sreyk 		    print_map(dsa->dsa_method, ikev2_auth_map));
8845e4d3a37Sreyk 		return (-1);
8855e4d3a37Sreyk 	}
88608c24fddStobhe 	keytype = EVP_PKEY_type(EVP_PKEY_id(((EVP_PKEY *)dsa->dsa_key)));
88748b975e3Smarkus 	if (sig == NULL) {
88848b975e3Smarkus 		log_debug("%s: signature missing", __func__);
88948b975e3Smarkus 		return (-1);
89048b975e3Smarkus 	}
8915e4d3a37Sreyk 	if (len < sizeof(oidlen)) {
89248b975e3Smarkus 		log_debug("%s: signature (%zu) too small for oid length",
89348b975e3Smarkus 		    __func__, len);
89448b975e3Smarkus 		return (-1);
89548b975e3Smarkus 	}
89648b975e3Smarkus 	memcpy(&oidlen, sig, sizeof(oidlen));
8975e4d3a37Sreyk 	if (len < (size_t)oidlen + sizeof(oidlen)) {
89848b975e3Smarkus 		log_debug("%s: signature (%zu) too small for oid (%u)",
89948b975e3Smarkus 		    __func__, len, oidlen);
90048b975e3Smarkus 		return (-1);
90148b975e3Smarkus 	}
90248b975e3Smarkus 	for (i = 0; i < nitems(schemes); i++) {
9035e4d3a37Sreyk 		if (keytype == schemes[i].sc_keytype &&
9045e4d3a37Sreyk 		    oidlen == schemes[i].sc_len &&
90572178c58Sreyk 		    memcmp(sig + 1, schemes[i].sc_oid,
90672178c58Sreyk 		    schemes[i].sc_len) == 0) {
90748b975e3Smarkus 			dsa->dsa_priv = (*schemes[i].sc_md)();
908466d2dbaStobhe 			dsa->dsa_flags = schemes[i].sc_flags;
90948b975e3Smarkus 			log_debug("%s: signature scheme %zd selected",
91048b975e3Smarkus 			    __func__, i);
91148b975e3Smarkus 			return (0);
91248b975e3Smarkus 		}
91348b975e3Smarkus 	}
91448b975e3Smarkus 	log_debug("%s: unsupported signature (%d)", __func__, oidlen);
91548b975e3Smarkus 	return (-1);
91648b975e3Smarkus }
91748b975e3Smarkus 
91848b975e3Smarkus int
91948b975e3Smarkus dsa_init(struct iked_dsa *dsa, const void *buf, size_t len)
92045ae9d61Sreyk {
921466d2dbaStobhe 	int		 ret;
922753a20acStobhe 	EVP_PKEY_CTX	*pctx = NULL;
92345ae9d61Sreyk 
92445ae9d61Sreyk 	if (dsa->dsa_hmac) {
92580ff32ddSmikeb 		if (!HMAC_Init_ex(dsa->dsa_ctx, ibuf_data(dsa->dsa_keydata),
926eef6c82aSclaudio 		    ibuf_size(dsa->dsa_keydata), dsa->dsa_priv, NULL))
92780ff32ddSmikeb 			return (-1);
92845ae9d61Sreyk 		return (0);
92945ae9d61Sreyk 	}
93045ae9d61Sreyk 
931466d2dbaStobhe 	if (dsa->dsa_sign) {
932466d2dbaStobhe 		if (force_rsa_pss &&
933466d2dbaStobhe 		    EVP_PKEY_base_id(dsa->dsa_key) == EVP_PKEY_RSA)
934466d2dbaStobhe 			dsa->dsa_flags = FLAG_RSA_PSS;
935466d2dbaStobhe 		ret = EVP_DigestSignInit(dsa->dsa_ctx, &pctx, dsa->dsa_priv,
936cb2fef99Stobhe 		    NULL, dsa->dsa_key);
937466d2dbaStobhe 	} else {
938466d2dbaStobhe 		/* sets dsa_priv, dsa_flags */
939466d2dbaStobhe 		if ((ret = _dsa_verify_init(dsa, buf, len)) != 0)
94048b975e3Smarkus 			return (ret);
941753a20acStobhe 		ret = EVP_DigestVerifyInit(dsa->dsa_ctx, &pctx, dsa->dsa_priv,
942cb2fef99Stobhe 		    NULL, dsa->dsa_key);
943466d2dbaStobhe 	}
944466d2dbaStobhe 	if (ret == 1 && dsa->dsa_flags == FLAG_RSA_PSS) {
945753a20acStobhe 		if (EVP_PKEY_CTX_set_rsa_padding(pctx,
946753a20acStobhe 		    RSA_PKCS1_PSS_PADDING) <= 0 ||
947753a20acStobhe 		    EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1) <= 0)
948753a20acStobhe 			return (-1);
949753a20acStobhe 	}
9506802616fStobhe 	if (_dsa_sign_encode(dsa, NULL, 0, NULL) < 0)
9516802616fStobhe 		return (-1);
95245ae9d61Sreyk 
953cb2fef99Stobhe 	return (ret == 1 ? 0 : -1);
95445ae9d61Sreyk }
95545ae9d61Sreyk 
95645ae9d61Sreyk int
95745ae9d61Sreyk dsa_update(struct iked_dsa *dsa, const void *buf, size_t len)
95845ae9d61Sreyk {
959cb2fef99Stobhe 	int	ret;
96045ae9d61Sreyk 
96145ae9d61Sreyk 	if (dsa->dsa_hmac)
96280ff32ddSmikeb 		ret = HMAC_Update(dsa->dsa_ctx, buf, len);
96345ae9d61Sreyk 	else if (dsa->dsa_sign)
964cb2fef99Stobhe 		ret = EVP_DigestSignUpdate(dsa->dsa_ctx, buf, len);
96545ae9d61Sreyk 	else
966cb2fef99Stobhe 		ret = EVP_DigestVerifyUpdate(dsa->dsa_ctx, buf, len);
96745ae9d61Sreyk 
968cb2fef99Stobhe 	return (ret == 1 ? 0 : -1);
96945ae9d61Sreyk }
97045ae9d61Sreyk 
97148b975e3Smarkus /* Prefix signature hash with encoded type */
97248b975e3Smarkus int
973cb2fef99Stobhe _dsa_sign_encode(struct iked_dsa *dsa, uint8_t *ptr, size_t len, size_t *offp)
97448b975e3Smarkus {
9755e4d3a37Sreyk 	int		 keytype;
976cb2fef99Stobhe 	size_t		 i, need;
9775e4d3a37Sreyk 
97848b975e3Smarkus 	if (offp)
97948b975e3Smarkus 		*offp = 0;
98048b975e3Smarkus 	if (dsa->dsa_method != IKEV2_AUTH_SIG)
98148b975e3Smarkus 		return (0);
9825e4d3a37Sreyk 	if (dsa->dsa_key == NULL)
9835e4d3a37Sreyk 		return (-1);
98408c24fddStobhe 	keytype = EVP_PKEY_type(EVP_PKEY_id(((EVP_PKEY *)dsa->dsa_key)));
9855e4d3a37Sreyk 	for (i = 0; i < nitems(schemes); i++) {
9865e4d3a37Sreyk 		/* XXX should avoid calling sc_md() each time... */
9875e4d3a37Sreyk 		if (keytype == schemes[i].sc_keytype &&
988466d2dbaStobhe 		    dsa->dsa_flags == schemes[i].sc_flags &&
9895e4d3a37Sreyk 		    (dsa->dsa_priv == (*schemes[i].sc_md)()))
9905e4d3a37Sreyk 			break;
9915e4d3a37Sreyk 	}
9925e4d3a37Sreyk 	if (i >= nitems(schemes))
99348b975e3Smarkus 		return (-1);
994cb2fef99Stobhe 	log_debug("%s: signature scheme %zd selected", __func__, i);
995cb2fef99Stobhe 	need = sizeof(ptr[0]) + schemes[i].sc_len;
99648b975e3Smarkus 	if (ptr) {
997cb2fef99Stobhe 		if (len < need)
998cb2fef99Stobhe 			return (-1);
9995e4d3a37Sreyk 		ptr[0] = schemes[i].sc_len;
10005e4d3a37Sreyk 		memcpy(ptr + sizeof(ptr[0]), schemes[i].sc_oid,
10015e4d3a37Sreyk 		    schemes[i].sc_len);
100248b975e3Smarkus 	}
100348b975e3Smarkus 	if (offp)
1004cb2fef99Stobhe 		*offp = need;
100548b975e3Smarkus 	return (0);
100648b975e3Smarkus }
100748b975e3Smarkus 
10085e4d3a37Sreyk /* Export size of encoded signature hash type */
10095e4d3a37Sreyk size_t
10105e4d3a37Sreyk dsa_prefix(struct iked_dsa *dsa)
10115e4d3a37Sreyk {
10125e4d3a37Sreyk 	size_t		off = 0;
10135e4d3a37Sreyk 
1014cb2fef99Stobhe 	if (_dsa_sign_encode(dsa, NULL, 0, &off) < 0)
10155e4d3a37Sreyk 		fatal("dsa_prefix: internal error");
10165e4d3a37Sreyk 	return off;
10175e4d3a37Sreyk }
10185e4d3a37Sreyk 
101945ae9d61Sreyk size_t
102045ae9d61Sreyk dsa_length(struct iked_dsa *dsa)
102145ae9d61Sreyk {
102245ae9d61Sreyk 	if (dsa->dsa_hmac)
102345ae9d61Sreyk 		return (EVP_MD_size(dsa->dsa_priv));
10245e4d3a37Sreyk 	switch (dsa->dsa_method) {
10255e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_256:
10265e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_384:
10275e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_521:
10285e4d3a37Sreyk 		/* size of concat(r|s) */
10295e4d3a37Sreyk 		return (2 * ((EVP_PKEY_bits(dsa->dsa_key) + 7) / 8));
10305e4d3a37Sreyk 	}
10315e4d3a37Sreyk 	return (dsa_prefix(dsa) + EVP_PKEY_size(dsa->dsa_key));
10325e4d3a37Sreyk }
10335e4d3a37Sreyk 
10345e4d3a37Sreyk int
10355e4d3a37Sreyk _dsa_sign_ecdsa(struct iked_dsa *dsa, uint8_t *ptr, size_t len)
10365e4d3a37Sreyk {
10375e4d3a37Sreyk 	ECDSA_SIG	*obj = NULL;
1038cb2fef99Stobhe 	uint8_t		*tmp = NULL;
10394e7f824bSotto 	const uint8_t	*p;
1040cb2fef99Stobhe 	size_t		 tmplen;
10415e4d3a37Sreyk 	int		 ret = -1;
10425e4d3a37Sreyk 	int		 bnlen, off;
104308c24fddStobhe 	const BIGNUM	*r, *s;
10445e4d3a37Sreyk 
10455e4d3a37Sreyk 	if (len % 2)
10465e4d3a37Sreyk 		goto done;	/* must be even */
10475e4d3a37Sreyk 	bnlen = len/2;
10485e4d3a37Sreyk 	/*
10495e4d3a37Sreyk 	 * (a) create DER signature into 'tmp' buffer
10505e4d3a37Sreyk 	 * (b) convert buffer to ECDSA_SIG object
10515e4d3a37Sreyk 	 * (c) concatenate the padded r|s BIGNUMS into 'ptr'
10525e4d3a37Sreyk 	 */
1053cb2fef99Stobhe 	if (EVP_DigestSignFinal(dsa->dsa_ctx, NULL, &tmplen) != 1)
10545e4d3a37Sreyk 		goto done;
1055cb2fef99Stobhe 	if ((tmp = calloc(1, tmplen)) == NULL)
10565e4d3a37Sreyk 		goto done;
1057cb2fef99Stobhe 	if (EVP_DigestSignFinal(dsa->dsa_ctx, tmp, &tmplen) != 1)
10585e4d3a37Sreyk 		goto done;
10594e7f824bSotto 	p = tmp;
1060f0ca6b40Stb 	if ((obj = d2i_ECDSA_SIG(NULL, &p, tmplen)) == NULL)
10615e4d3a37Sreyk 		goto done;
106208c24fddStobhe 	ECDSA_SIG_get0(obj, &r, &s);
106308c24fddStobhe 	if (BN_num_bytes(r) > bnlen || BN_num_bytes(s) > bnlen)
10645e4d3a37Sreyk 		goto done;
10655e4d3a37Sreyk 	memset(ptr, 0, len);
106608c24fddStobhe 	off = bnlen - BN_num_bytes(r);
106708c24fddStobhe 	BN_bn2bin(r, ptr + off);
106808c24fddStobhe 	off = 2 * bnlen - BN_num_bytes(s);
106908c24fddStobhe 	BN_bn2bin(s, ptr + off);
10705e4d3a37Sreyk 	ret = 0;
10715e4d3a37Sreyk  done:
1072cb2fef99Stobhe 	free(tmp);
10735e4d3a37Sreyk 	ECDSA_SIG_free(obj);
10747199b42cStobhe 
10755e4d3a37Sreyk 	return (ret);
107645ae9d61Sreyk }
107745ae9d61Sreyk 
107845ae9d61Sreyk ssize_t
107945ae9d61Sreyk dsa_sign_final(struct iked_dsa *dsa, void *buf, size_t len)
108045ae9d61Sreyk {
1081cb2fef99Stobhe 	unsigned int	 hmaclen;
108248b975e3Smarkus 	size_t		 off = 0;
1083d09d3a7dSreyk 	uint8_t		*ptr = buf;
108445ae9d61Sreyk 
108545ae9d61Sreyk 	if (len < dsa_length(dsa))
108645ae9d61Sreyk 		return (-1);
108745ae9d61Sreyk 
108880ff32ddSmikeb 	if (dsa->dsa_hmac) {
1089cb2fef99Stobhe 		if (!HMAC_Final(dsa->dsa_ctx, buf, &hmaclen))
109080ff32ddSmikeb 			return (-1);
1091cb2fef99Stobhe 		if (hmaclen > INT_MAX)
1092cb2fef99Stobhe 			return (-1);
1093cb2fef99Stobhe 		return (ssize_t)hmaclen;
109480ff32ddSmikeb 	} else {
10955e4d3a37Sreyk 		switch (dsa->dsa_method) {
10965e4d3a37Sreyk 		case IKEV2_AUTH_ECDSA_256:
10975e4d3a37Sreyk 		case IKEV2_AUTH_ECDSA_384:
10985e4d3a37Sreyk 		case IKEV2_AUTH_ECDSA_521:
10995e4d3a37Sreyk 			if (_dsa_sign_ecdsa(dsa, buf, len) < 0)
11005e4d3a37Sreyk 				return (-1);
1101cb2fef99Stobhe 			return (len);
11025e4d3a37Sreyk 		default:
1103cb2fef99Stobhe 			if (_dsa_sign_encode(dsa, ptr, len, &off) < 0)
110448b975e3Smarkus 				return (-1);
1105cb2fef99Stobhe 			if (off > len)
110645ae9d61Sreyk 				return (-1);
1107cb2fef99Stobhe 			len -= off;
1108cb2fef99Stobhe 			ptr += off;
1109cb2fef99Stobhe 			if (EVP_DigestSignFinal(dsa->dsa_ctx, ptr, &len) != 1)
1110cb2fef99Stobhe 				return (-1);
1111cb2fef99Stobhe 			return (len + off);
11125e4d3a37Sreyk 		}
111345ae9d61Sreyk 	}
1114cb2fef99Stobhe 	return (-1);
111545ae9d61Sreyk }
111645ae9d61Sreyk 
11175e4d3a37Sreyk int
11185e4d3a37Sreyk _dsa_verify_prepare(struct iked_dsa *dsa, uint8_t **sigp, size_t *lenp,
11195e4d3a37Sreyk     uint8_t **freemep)
112048b975e3Smarkus {
11215e4d3a37Sreyk 	ECDSA_SIG	*obj = NULL;
11225e4d3a37Sreyk 	uint8_t		*ptr = NULL;
1123959c447eSbluhm 	size_t		 bnlen, off;
1124959c447eSbluhm 	ssize_t		 len;
11255e4d3a37Sreyk 	int		 ret = -1;
112608c24fddStobhe 	BIGNUM		*r = NULL, *s = NULL;
11275e4d3a37Sreyk 
11285e4d3a37Sreyk 	*freemep = NULL;	/* don't return garbage in case of an error */
11295e4d3a37Sreyk 
11305e4d3a37Sreyk 	switch (dsa->dsa_method) {
11315e4d3a37Sreyk 	case IKEV2_AUTH_SIG:
113248b975e3Smarkus 		/*
11335e4d3a37Sreyk 		 * The first byte of the signature encodes the OID
11345e4d3a37Sreyk 		 * prefix length which we need to skip.
113548b975e3Smarkus 		 */
11365e4d3a37Sreyk 		off = (*sigp)[0] + 1;
11375e4d3a37Sreyk 		*sigp = *sigp + off;
11385e4d3a37Sreyk 		*lenp = *lenp - off;
11395e4d3a37Sreyk 		*freemep = NULL;
11405e4d3a37Sreyk 		ret = 0;
11415e4d3a37Sreyk 		break;
11425e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_256:
11435e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_384:
11445e4d3a37Sreyk 	case IKEV2_AUTH_ECDSA_521:
11455e4d3a37Sreyk 		/*
11465e4d3a37Sreyk 		 * sigp points to concatenation r|s, while EVP_VerifyFinal()
11475e4d3a37Sreyk 		 * expects the signature as a DER-encoded blob (of the two
11485e4d3a37Sreyk 		 * values), so we need to convert the signature in a new
11495e4d3a37Sreyk 		 * buffer (we cannot override the given buffer) and the caller
11505e4d3a37Sreyk 		 * has to free this buffer ('freeme').
11515e4d3a37Sreyk 		 */
11525e4d3a37Sreyk 		if (*lenp < 64 || *lenp > 132 || *lenp % 2)
11535e4d3a37Sreyk 			goto done;
11545e4d3a37Sreyk 		bnlen = (*lenp)/2;
11555e4d3a37Sreyk 		/* sigp points to concatenation: r|s */
11565e4d3a37Sreyk 		if ((obj = ECDSA_SIG_new()) == NULL ||
115708c24fddStobhe 		    (r = BN_bin2bn(*sigp, bnlen, NULL)) == NULL ||
115808c24fddStobhe 		    (s = BN_bin2bn(*sigp+bnlen, bnlen, NULL)) == NULL ||
115908c24fddStobhe 		    ECDSA_SIG_set0(obj, r, s) == 0 ||
1160959c447eSbluhm 		    (len = i2d_ECDSA_SIG(obj, &ptr)) <= 0)
11615e4d3a37Sreyk 			goto done;
116208c24fddStobhe 		r = s = NULL;
11635e4d3a37Sreyk 		*lenp = len;
11645e4d3a37Sreyk 		*sigp = ptr;
11655e4d3a37Sreyk 		*freemep = ptr;
11665e4d3a37Sreyk 		ptr = NULL;
11675e4d3a37Sreyk 		ret = 0;
11685e4d3a37Sreyk 		break;
11695e4d3a37Sreyk 	default:
117048b975e3Smarkus 		return (0);
117148b975e3Smarkus 	}
11725e4d3a37Sreyk  done:
117308c24fddStobhe 	BN_clear_free(r);
117408c24fddStobhe 	BN_clear_free(s);
11755e4d3a37Sreyk 	free(ptr);
11765e4d3a37Sreyk 	ECDSA_SIG_free(obj);
11777199b42cStobhe 
11785e4d3a37Sreyk 	return (ret);
11795e4d3a37Sreyk }
118048b975e3Smarkus 
118145ae9d61Sreyk ssize_t
118245ae9d61Sreyk dsa_verify_final(struct iked_dsa *dsa, void *buf, size_t len)
118345ae9d61Sreyk {
1184d09d3a7dSreyk 	uint8_t		 sig[EVP_MAX_MD_SIZE];
11855e4d3a37Sreyk 	uint8_t		*ptr = buf, *freeme = NULL;
1186d09d3a7dSreyk 	unsigned int	 siglen = sizeof(sig);
118745ae9d61Sreyk 
118845ae9d61Sreyk 	if (dsa->dsa_hmac) {
118980ff32ddSmikeb 		if (!HMAC_Final(dsa->dsa_ctx, sig, &siglen))
119080ff32ddSmikeb 			return (-1);
119145ae9d61Sreyk 		if (siglen != len || memcmp(buf, sig, siglen) != 0)
119245ae9d61Sreyk 			return (-1);
119345ae9d61Sreyk 	} else {
11945e4d3a37Sreyk 		if (_dsa_verify_prepare(dsa, &ptr, &len, &freeme) < 0)
119548b975e3Smarkus 			return (-1);
1196cb2fef99Stobhe 		if (EVP_DigestVerifyFinal(dsa->dsa_ctx, ptr, len) != 1) {
1197bac832a5Stobhe 			OPENSSL_free(freeme);
119886cf9d9cSmarkus 			ca_sslerror(__func__);
119945ae9d61Sreyk 			return (-1);
120045ae9d61Sreyk 		}
1201bac832a5Stobhe 		OPENSSL_free(freeme);
120245ae9d61Sreyk 	}
120345ae9d61Sreyk 
120445ae9d61Sreyk 	return (0);
120545ae9d61Sreyk }
1206