1*a91a2465SEd Maste /* $OpenBSD: sshbuf-getput-crypto.c,v 1.11 2024/02/01 02:37:33 djm Exp $ */ 2a0ee8cc6SDag-Erling Smørgrav /* 3a0ee8cc6SDag-Erling Smørgrav * Copyright (c) 2011 Damien Miller 4a0ee8cc6SDag-Erling Smørgrav * 5a0ee8cc6SDag-Erling Smørgrav * Permission to use, copy, modify, and distribute this software for any 6a0ee8cc6SDag-Erling Smørgrav * purpose with or without fee is hereby granted, provided that the above 7a0ee8cc6SDag-Erling Smørgrav * copyright notice and this permission notice appear in all copies. 8a0ee8cc6SDag-Erling Smørgrav * 9a0ee8cc6SDag-Erling Smørgrav * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10a0ee8cc6SDag-Erling Smørgrav * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11a0ee8cc6SDag-Erling Smørgrav * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12a0ee8cc6SDag-Erling Smørgrav * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13a0ee8cc6SDag-Erling Smørgrav * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14a0ee8cc6SDag-Erling Smørgrav * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15a0ee8cc6SDag-Erling Smørgrav * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16a0ee8cc6SDag-Erling Smørgrav */ 17a0ee8cc6SDag-Erling Smørgrav 18a0ee8cc6SDag-Erling Smørgrav #define SSHBUF_INTERNAL 19a0ee8cc6SDag-Erling Smørgrav #include "includes.h" 20a0ee8cc6SDag-Erling Smørgrav 21a0ee8cc6SDag-Erling Smørgrav #include <sys/types.h> 22a0ee8cc6SDag-Erling Smørgrav #include <stdlib.h> 23a0ee8cc6SDag-Erling Smørgrav #include <stdio.h> 24a0ee8cc6SDag-Erling Smørgrav #include <string.h> 25a0ee8cc6SDag-Erling Smørgrav 2619261079SEd Maste #ifdef WITH_OPENSSL 27a0ee8cc6SDag-Erling Smørgrav #include <openssl/bn.h> 28a0ee8cc6SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 29a0ee8cc6SDag-Erling Smørgrav # include <openssl/ec.h> 30a0ee8cc6SDag-Erling Smørgrav #endif /* OPENSSL_HAS_ECC */ 31a0ee8cc6SDag-Erling Smørgrav 32a0ee8cc6SDag-Erling Smørgrav #include "ssherr.h" 33a0ee8cc6SDag-Erling Smørgrav #include "sshbuf.h" 34a0ee8cc6SDag-Erling Smørgrav 35a0ee8cc6SDag-Erling Smørgrav int 3619261079SEd Maste sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp) 37a0ee8cc6SDag-Erling Smørgrav { 3819261079SEd Maste BIGNUM *v; 39a0ee8cc6SDag-Erling Smørgrav const u_char *d; 40a0ee8cc6SDag-Erling Smørgrav size_t len; 41a0ee8cc6SDag-Erling Smørgrav int r; 42a0ee8cc6SDag-Erling Smørgrav 4319261079SEd Maste if (valp != NULL) 4419261079SEd Maste *valp = NULL; 45bc5531deSDag-Erling Smørgrav if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0) 46a0ee8cc6SDag-Erling Smørgrav return r; 4719261079SEd Maste if (valp != NULL) { 4819261079SEd Maste if ((v = BN_new()) == NULL || 4919261079SEd Maste BN_bin2bn(d, len, v) == NULL) { 5019261079SEd Maste BN_clear_free(v); 51a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 52a0ee8cc6SDag-Erling Smørgrav } 5319261079SEd Maste *valp = v; 54a0ee8cc6SDag-Erling Smørgrav } 55a0ee8cc6SDag-Erling Smørgrav return 0; 56a0ee8cc6SDag-Erling Smørgrav } 57a0ee8cc6SDag-Erling Smørgrav 58a0ee8cc6SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 59a0ee8cc6SDag-Erling Smørgrav static int 60a0ee8cc6SDag-Erling Smørgrav get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g) 61a0ee8cc6SDag-Erling Smørgrav { 62a0ee8cc6SDag-Erling Smørgrav /* Refuse overlong bignums */ 63a0ee8cc6SDag-Erling Smørgrav if (len == 0 || len > SSHBUF_MAX_ECPOINT) 64a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ECPOINT_TOO_LARGE; 65a0ee8cc6SDag-Erling Smørgrav /* Only handle uncompressed points */ 66a0ee8cc6SDag-Erling Smørgrav if (*d != POINT_CONVERSION_UNCOMPRESSED) 67a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_FORMAT; 68a0ee8cc6SDag-Erling Smørgrav if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1) 69a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_FORMAT; /* XXX assumption */ 70a0ee8cc6SDag-Erling Smørgrav return 0; 71a0ee8cc6SDag-Erling Smørgrav } 72a0ee8cc6SDag-Erling Smørgrav 73a0ee8cc6SDag-Erling Smørgrav int 74a0ee8cc6SDag-Erling Smørgrav sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g) 75a0ee8cc6SDag-Erling Smørgrav { 76a0ee8cc6SDag-Erling Smørgrav const u_char *d; 77a0ee8cc6SDag-Erling Smørgrav size_t len; 78a0ee8cc6SDag-Erling Smørgrav int r; 79a0ee8cc6SDag-Erling Smørgrav 80a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) 81a0ee8cc6SDag-Erling Smørgrav return r; 82a0ee8cc6SDag-Erling Smørgrav if ((r = get_ec(d, len, v, g)) != 0) 83a0ee8cc6SDag-Erling Smørgrav return r; 84a0ee8cc6SDag-Erling Smørgrav /* Skip string */ 85a0ee8cc6SDag-Erling Smørgrav if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { 86a0ee8cc6SDag-Erling Smørgrav /* Shouldn't happen */ 87a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); 88a0ee8cc6SDag-Erling Smørgrav SSHBUF_ABORT(); 89a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; 90a0ee8cc6SDag-Erling Smørgrav } 91a0ee8cc6SDag-Erling Smørgrav return 0; 92a0ee8cc6SDag-Erling Smørgrav } 93a0ee8cc6SDag-Erling Smørgrav 94a0ee8cc6SDag-Erling Smørgrav int 95a0ee8cc6SDag-Erling Smørgrav sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v) 96a0ee8cc6SDag-Erling Smørgrav { 97a0ee8cc6SDag-Erling Smørgrav EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v)); 98a0ee8cc6SDag-Erling Smørgrav int r; 99a0ee8cc6SDag-Erling Smørgrav const u_char *d; 100a0ee8cc6SDag-Erling Smørgrav size_t len; 101a0ee8cc6SDag-Erling Smørgrav 102a0ee8cc6SDag-Erling Smørgrav if (pt == NULL) { 103a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL")); 104a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; 105a0ee8cc6SDag-Erling Smørgrav } 106a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) { 107a0ee8cc6SDag-Erling Smørgrav EC_POINT_free(pt); 108a0ee8cc6SDag-Erling Smørgrav return r; 109a0ee8cc6SDag-Erling Smørgrav } 110a0ee8cc6SDag-Erling Smørgrav if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) { 111a0ee8cc6SDag-Erling Smørgrav EC_POINT_free(pt); 112a0ee8cc6SDag-Erling Smørgrav return r; 113a0ee8cc6SDag-Erling Smørgrav } 114a0ee8cc6SDag-Erling Smørgrav if (EC_KEY_set_public_key(v, pt) != 1) { 115a0ee8cc6SDag-Erling Smørgrav EC_POINT_free(pt); 116a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_ALLOC_FAIL; /* XXX assumption */ 117a0ee8cc6SDag-Erling Smørgrav } 118a0ee8cc6SDag-Erling Smørgrav EC_POINT_free(pt); 119a0ee8cc6SDag-Erling Smørgrav /* Skip string */ 120a0ee8cc6SDag-Erling Smørgrav if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) { 121a0ee8cc6SDag-Erling Smørgrav /* Shouldn't happen */ 122a0ee8cc6SDag-Erling Smørgrav SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR")); 123a0ee8cc6SDag-Erling Smørgrav SSHBUF_ABORT(); 124a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; 125a0ee8cc6SDag-Erling Smørgrav } 126a0ee8cc6SDag-Erling Smørgrav return 0; 127a0ee8cc6SDag-Erling Smørgrav } 128a0ee8cc6SDag-Erling Smørgrav #endif /* OPENSSL_HAS_ECC */ 129a0ee8cc6SDag-Erling Smørgrav 130a0ee8cc6SDag-Erling Smørgrav int 131a0ee8cc6SDag-Erling Smørgrav sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v) 132a0ee8cc6SDag-Erling Smørgrav { 133a0ee8cc6SDag-Erling Smørgrav u_char d[SSHBUF_MAX_BIGNUM + 1]; 134a0ee8cc6SDag-Erling Smørgrav int len = BN_num_bytes(v), prepend = 0, r; 135a0ee8cc6SDag-Erling Smørgrav 136a0ee8cc6SDag-Erling Smørgrav if (len < 0 || len > SSHBUF_MAX_BIGNUM) 137a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 138a0ee8cc6SDag-Erling Smørgrav *d = '\0'; 139a0ee8cc6SDag-Erling Smørgrav if (BN_bn2bin(v, d + 1) != len) 140a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ 141a0ee8cc6SDag-Erling Smørgrav /* If MSB is set, prepend a \0 */ 142a0ee8cc6SDag-Erling Smørgrav if (len > 0 && (d[1] & 0x80) != 0) 143a0ee8cc6SDag-Erling Smørgrav prepend = 1; 144a0ee8cc6SDag-Erling Smørgrav if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) { 145fc1ba28aSDag-Erling Smørgrav explicit_bzero(d, sizeof(d)); 146a0ee8cc6SDag-Erling Smørgrav return r; 147a0ee8cc6SDag-Erling Smørgrav } 148fc1ba28aSDag-Erling Smørgrav explicit_bzero(d, sizeof(d)); 149a0ee8cc6SDag-Erling Smørgrav return 0; 150a0ee8cc6SDag-Erling Smørgrav } 151a0ee8cc6SDag-Erling Smørgrav 152a0ee8cc6SDag-Erling Smørgrav #ifdef OPENSSL_HAS_ECC 153a0ee8cc6SDag-Erling Smørgrav int 154a0ee8cc6SDag-Erling Smørgrav sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g) 155a0ee8cc6SDag-Erling Smørgrav { 156a0ee8cc6SDag-Erling Smørgrav u_char d[SSHBUF_MAX_ECPOINT]; 157a0ee8cc6SDag-Erling Smørgrav size_t len; 158a0ee8cc6SDag-Erling Smørgrav int ret; 159a0ee8cc6SDag-Erling Smørgrav 160a0ee8cc6SDag-Erling Smørgrav if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, 16119261079SEd Maste NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) { 162a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INVALID_ARGUMENT; 163a0ee8cc6SDag-Erling Smørgrav } 164a0ee8cc6SDag-Erling Smørgrav if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED, 16519261079SEd Maste d, len, NULL) != len) { 166a0ee8cc6SDag-Erling Smørgrav return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */ 167a0ee8cc6SDag-Erling Smørgrav } 168a0ee8cc6SDag-Erling Smørgrav ret = sshbuf_put_string(buf, d, len); 169fc1ba28aSDag-Erling Smørgrav explicit_bzero(d, len); 170a0ee8cc6SDag-Erling Smørgrav return ret; 171a0ee8cc6SDag-Erling Smørgrav } 172a0ee8cc6SDag-Erling Smørgrav 173a0ee8cc6SDag-Erling Smørgrav int 174a0ee8cc6SDag-Erling Smørgrav sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v) 175a0ee8cc6SDag-Erling Smørgrav { 176a0ee8cc6SDag-Erling Smørgrav return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v), 177a0ee8cc6SDag-Erling Smørgrav EC_KEY_get0_group(v)); 178a0ee8cc6SDag-Erling Smørgrav } 179a0ee8cc6SDag-Erling Smørgrav #endif /* OPENSSL_HAS_ECC */ 18019261079SEd Maste #endif /* WITH_OPENSSL */ 181