Coverage Report

Created: 2024-06-18 06:23

/src/hpn-ssh/sshbuf-getput-crypto.c
Line
Count
Source (jump to first uncovered line)
1
/*  $OpenBSD: sshbuf-getput-crypto.c,v 1.11 2024/02/01 02:37:33 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
18
#define SSHBUF_INTERNAL
19
#include "includes.h"
20
21
#include <sys/types.h>
22
#include <stdlib.h>
23
#include <stdio.h>
24
#include <string.h>
25
26
#ifdef WITH_OPENSSL
27
#include <openssl/bn.h>
28
#ifdef OPENSSL_HAS_ECC
29
# include <openssl/ec.h>
30
#endif /* OPENSSL_HAS_ECC */
31
32
#include "ssherr.h"
33
#include "sshbuf.h"
34
35
int
36
sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
37
5.96k
{
38
5.96k
  BIGNUM *v;
39
5.96k
  const u_char *d;
40
5.96k
  size_t len;
41
5.96k
  int r;
42
43
5.96k
  if (valp != NULL)
44
5.96k
    *valp = NULL;
45
5.96k
  if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
46
229
    return r;
47
5.73k
  if (valp != NULL) {
48
5.73k
    if ((v = BN_new()) == NULL ||
49
5.73k
        BN_bin2bn(d, len, v) == NULL) {
50
0
      BN_clear_free(v);
51
0
      return SSH_ERR_ALLOC_FAIL;
52
0
    }
53
5.73k
    *valp = v;
54
5.73k
  }
55
5.73k
  return 0;
56
5.73k
}
57
58
#ifdef OPENSSL_HAS_ECC
59
static int
60
get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
61
83
{
62
  /* Refuse overlong bignums */
63
83
  if (len == 0 || len > SSHBUF_MAX_ECPOINT)
64
52
    return SSH_ERR_ECPOINT_TOO_LARGE;
65
  /* Only handle uncompressed points */
66
31
  if (*d != POINT_CONVERSION_UNCOMPRESSED)
67
30
    return SSH_ERR_INVALID_FORMAT;
68
1
  if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
69
1
    return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
70
0
  return 0;
71
1
}
72
73
int
74
sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
75
0
{
76
0
  const u_char *d;
77
0
  size_t len;
78
0
  int r;
79
80
0
  if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
81
0
    return r;
82
0
  if ((r = get_ec(d, len, v, g)) != 0)
83
0
    return r;
84
  /* Skip string */
85
0
  if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
86
    /* Shouldn't happen */
87
0
    SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
88
0
    SSHBUF_ABORT();
89
0
    return SSH_ERR_INTERNAL_ERROR;
90
0
  }
91
0
  return 0;
92
0
}
93
94
int
95
sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
96
147
{
97
147
  EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
98
147
  int r;
99
147
  const u_char *d;
100
147
  size_t len;
101
102
147
  if (pt == NULL) {
103
0
    SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
104
0
    return SSH_ERR_ALLOC_FAIL;
105
0
  }
106
147
  if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
107
64
    EC_POINT_free(pt);
108
64
    return r;
109
64
  }
110
83
  if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
111
83
    EC_POINT_free(pt);
112
83
    return r;
113
83
  }
114
0
  if (EC_KEY_set_public_key(v, pt) != 1) {
115
0
    EC_POINT_free(pt);
116
0
    return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
117
0
  }
118
0
  EC_POINT_free(pt);
119
  /* Skip string */
120
0
  if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
121
    /* Shouldn't happen */
122
0
    SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
123
0
    SSHBUF_ABORT();
124
0
    return SSH_ERR_INTERNAL_ERROR;
125
0
  }
126
0
  return 0;
127
0
}
128
#endif /* OPENSSL_HAS_ECC */
129
130
int
131
sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
132
0
{
133
0
  u_char d[SSHBUF_MAX_BIGNUM + 1];
134
0
  int len = BN_num_bytes(v), prepend = 0, r;
135
136
0
  if (len < 0 || len > SSHBUF_MAX_BIGNUM)
137
0
    return SSH_ERR_INVALID_ARGUMENT;
138
0
  *d = '\0';
139
0
  if (BN_bn2bin(v, d + 1) != len)
140
0
    return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
141
  /* If MSB is set, prepend a \0 */
142
0
  if (len > 0 && (d[1] & 0x80) != 0)
143
0
    prepend = 1;
144
0
  if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
145
0
    explicit_bzero(d, sizeof(d));
146
0
    return r;
147
0
  }
148
0
  explicit_bzero(d, sizeof(d));
149
0
  return 0;
150
0
}
151
152
#ifdef OPENSSL_HAS_ECC
153
int
154
sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
155
0
{
156
0
  u_char d[SSHBUF_MAX_ECPOINT];
157
0
  size_t len;
158
0
  int ret;
159
160
0
  if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
161
0
      NULL, 0, NULL)) > SSHBUF_MAX_ECPOINT) {
162
0
    return SSH_ERR_INVALID_ARGUMENT;
163
0
  }
164
0
  if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
165
0
      d, len, NULL) != len) {
166
0
    return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
167
0
  }
168
0
  ret = sshbuf_put_string(buf, d, len);
169
0
  explicit_bzero(d, len);
170
0
  return ret;
171
0
}
172
173
int
174
sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
175
0
{
176
0
  return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
177
0
      EC_KEY_get0_group(v));
178
0
}
179
#endif /* OPENSSL_HAS_ECC */
180
#endif /* WITH_OPENSSL */