Fix CVE-2017-6891 in minitasn1 code
[platform/upstream/gnutls.git] / lib / gnutls_ecc.c
1 /*
2  * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
8  * The GnuTLS is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>
20  *
21  */
22
23 /* Helper functions for ECC handling 
24  * based on public domain code by Tom St. Dennis.
25  */
26 #include <gnutls_int.h>
27 #include <gnutls_mpi.h>
28 #include <gnutls_ecc.h>
29 #include <algorithms.h>
30 #include <gnutls_errors.h>
31
32 int
33 _gnutls_ecc_ansi_x963_export(gnutls_ecc_curve_t curve, bigint_t x,
34                              bigint_t y, gnutls_datum_t * out)
35 {
36         int numlen = gnutls_ecc_curve_get_size(curve);
37         int byte_size, ret;
38         size_t size;
39
40         if (numlen == 0)
41                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
42
43         out->size = 1 + 2 * numlen;
44
45         out->data = gnutls_malloc(out->size);
46         if (out->data == NULL)
47                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
48
49         memset(out->data, 0, out->size);
50
51         /* store byte 0x04 */
52         out->data[0] = 0x04;
53
54         /* pad and store x */
55         byte_size = (_gnutls_mpi_get_nbits(x) + 7) / 8;
56         if (numlen < byte_size) {
57                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
58                 goto cleanup;
59         }
60
61         size = out->size - (1 + (numlen - byte_size));
62         ret =
63             _gnutls_mpi_print(x, &out->data[1 + (numlen - byte_size)],
64                               &size);
65         if (ret < 0) {
66                 gnutls_assert();
67                 goto cleanup;
68         }
69
70         byte_size = (_gnutls_mpi_get_nbits(y) + 7) / 8;
71         if (numlen < byte_size) {
72                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
73                 goto cleanup;
74         }
75
76         size = out->size - (1 + (numlen + numlen - byte_size));
77         ret =
78             _gnutls_mpi_print(y,
79                               &out->data[1 + numlen + numlen - byte_size],
80                               &size);
81         if (ret < 0) {
82                 gnutls_assert();
83                 goto cleanup;
84         }
85
86         /* pad and store y */
87         return 0;
88  cleanup:
89         _gnutls_free_datum(out);
90         return ret;
91 }
92
93
94 int
95 _gnutls_ecc_ansi_x963_import(const uint8_t * in,
96                              unsigned long inlen, bigint_t * x,
97                              bigint_t * y)
98 {
99         int ret;
100
101         /* must be odd */
102         if ((inlen & 1) == 0) {
103                 return GNUTLS_E_INVALID_REQUEST;
104         }
105
106         /* check for 4  */
107         if (in[0] != 4) {
108                 return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
109         }
110
111         /* read data */
112         ret = _gnutls_mpi_init_scan(x, in + 1, (inlen - 1) >> 1);
113         if (ret < 0)
114                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
115
116         ret =
117             _gnutls_mpi_init_scan(y, in + 1 + ((inlen - 1) >> 1),
118                              (inlen - 1) >> 1);
119         if (ret < 0) {
120                 _gnutls_mpi_release(x);
121                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
122         }
123
124         return 0;
125 }