1/*
2 * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4 *
5 * Licensed under the OpenSSL license (the "License").  You may not use
6 * this file except in compliance with the License.  You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
9 */
10
11#include <string.h>
12
13#include <openssl/err.h>
14#include <openssl/opensslv.h>
15
16#include "ec_local.h"
17
18int EC_POINT_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
19                                        const BIGNUM *x, int y_bit, BN_CTX *ctx)
20{
21    if (group->meth->point_set_compressed_coordinates == NULL
22        && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
23        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
24              ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
25        return 0;
26    }
27    if (!ec_point_is_compat(point, group)) {
28        ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
29              EC_R_INCOMPATIBLE_OBJECTS);
30        return 0;
31    }
32    if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
33        if (group->meth->field_type == NID_X9_62_prime_field)
34            return ec_GFp_simple_set_compressed_coordinates(group, point, x,
35                                                            y_bit, ctx);
36        else
37#ifdef OPENSSL_NO_EC2M
38        {
39            ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES,
40                  EC_R_GF2M_NOT_SUPPORTED);
41            return 0;
42        }
43#else
44            return ec_GF2m_simple_set_compressed_coordinates(group, point, x,
45                                                             y_bit, ctx);
46#endif
47    }
48    return group->meth->point_set_compressed_coordinates(group, point, x,
49                                                         y_bit, ctx);
50}
51
52#if OPENSSL_API_COMPAT < 0x10200000L
53int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group,
54                                            EC_POINT *point, const BIGNUM *x,
55                                            int y_bit, BN_CTX *ctx)
56{
57    return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
58}
59
60# ifndef OPENSSL_NO_EC2M
61int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group,
62                                             EC_POINT *point, const BIGNUM *x,
63                                             int y_bit, BN_CTX *ctx)
64{
65    return EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx);
66}
67# endif
68#endif
69
70size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point,
71                          point_conversion_form_t form, unsigned char *buf,
72                          size_t len, BN_CTX *ctx)
73{
74    if (group->meth->point2oct == 0
75        && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
76        ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
77        return 0;
78    }
79    if (!ec_point_is_compat(point, group)) {
80        ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
81        return 0;
82    }
83    if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
84        if (group->meth->field_type == NID_X9_62_prime_field)
85            return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
86        else
87#ifdef OPENSSL_NO_EC2M
88        {
89            ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_GF2M_NOT_SUPPORTED);
90            return 0;
91        }
92#else
93            return ec_GF2m_simple_point2oct(group, point,
94                                            form, buf, len, ctx);
95#endif
96    }
97
98    return group->meth->point2oct(group, point, form, buf, len, ctx);
99}
100
101int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
102                       const unsigned char *buf, size_t len, BN_CTX *ctx)
103{
104    if (group->meth->oct2point == 0
105        && !(group->meth->flags & EC_FLAGS_DEFAULT_OCT)) {
106        ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
107        return 0;
108    }
109    if (!ec_point_is_compat(point, group)) {
110        ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
111        return 0;
112    }
113    if (group->meth->flags & EC_FLAGS_DEFAULT_OCT) {
114        if (group->meth->field_type == NID_X9_62_prime_field)
115            return ec_GFp_simple_oct2point(group, point, buf, len, ctx);
116        else
117#ifdef OPENSSL_NO_EC2M
118        {
119            ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_GF2M_NOT_SUPPORTED);
120            return 0;
121        }
122#else
123            return ec_GF2m_simple_oct2point(group, point, buf, len, ctx);
124#endif
125    }
126    return group->meth->oct2point(group, point, buf, len, ctx);
127}
128
129size_t EC_POINT_point2buf(const EC_GROUP *group, const EC_POINT *point,
130                          point_conversion_form_t form,
131                          unsigned char **pbuf, BN_CTX *ctx)
132{
133    size_t len;
134    unsigned char *buf;
135
136    len = EC_POINT_point2oct(group, point, form, NULL, 0, NULL);
137    if (len == 0)
138        return 0;
139    if ((buf = OPENSSL_malloc(len)) == NULL) {
140        ECerr(EC_F_EC_POINT_POINT2BUF, ERR_R_MALLOC_FAILURE);
141        return 0;
142    }
143    len = EC_POINT_point2oct(group, point, form, buf, len, ctx);
144    if (len == 0) {
145        OPENSSL_free(buf);
146        return 0;
147    }
148    *pbuf = buf;
149    return len;
150}
151