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