1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ====================================================================
2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without
5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions
6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met:
7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright
9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer.
10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright
12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    notice, this list of conditions and the following disclaimer in
13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    the documentation and/or other materials provided with the
14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    distribution.
15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this
17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    software must display the following acknowledgment:
18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    endorse or promote products derived from this software without
23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    prior written permission. For written permission, please contact
24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    openssl-core@OpenSSL.org.
25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL"
27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    nor may "OpenSSL" appear in their names without prior written
28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    permission of the OpenSSL Project.
29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following
31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    acknowledgment:
32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    "This product includes software developed by the OpenSSL Project
33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE.
47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ====================================================================
48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley *
49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young
50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com).  This product includes software written by Tim
51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). */
52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ecdsa.h>
54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
55b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <limits.h>
56b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <string.h>
57b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
58b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <openssl/bn.h>
59b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <openssl/bytestring.h>
60b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root#include <openssl/err.h>
61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ec_key.h>
62e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley#include <openssl/mem.h>
63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
644969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin#include "../bytestring/internal.h"
658ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../fipsmodule/ec/internal.h"
668ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan#include "../internal.h"
678ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
688ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
698ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanint ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
708ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan               unsigned int *sig_len, const EC_KEY *eckey) {
718ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
728ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len,
738ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                                   (EC_KEY*) eckey /* cast away const */);
748ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
758ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
768ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL,
778ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                       eckey);
788ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan}
798ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
808ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanint ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
818ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                  uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
828ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                  const BIGNUM *r, const EC_KEY *eckey) {
838ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  int ret = 0;
848ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ECDSA_SIG *s = NULL;
858ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
868ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
878ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
888ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    *sig_len = 0;
898ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    goto err;
908ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
918ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
928ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  s = ECDSA_do_sign_ex(digest, digest_len, kinv, r, eckey);
938ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (s == NULL) {
948ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    *sig_len = 0;
958ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    goto err;
968ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
978ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
988ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  CBB cbb;
998ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  CBB_zero(&cbb);
1008ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  size_t len;
1018ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (!CBB_init_fixed(&cbb, sig, ECDSA_size(eckey)) ||
1028ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan      !ECDSA_SIG_marshal(&cbb, s) ||
1038ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan      !CBB_finish(&cbb, NULL, &len)) {
1048ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
1058ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    CBB_cleanup(&cbb);
1068ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    *sig_len = 0;
1078ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    goto err;
1088ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1098ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  *sig_len = (unsigned)len;
1108ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ret = 1;
1118ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1128ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanerr:
1138ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ECDSA_SIG_free(s);
1148ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  return ret;
1158ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan}
1168ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1178ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanint ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
1188ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan                 const uint8_t *sig, size_t sig_len, const EC_KEY *eckey) {
1198ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ECDSA_SIG *s;
1208ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  int ret = 0;
1218ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  uint8_t *der = NULL;
1228ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1238ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  /* Decode the ECDSA signature. */
1248ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  s = ECDSA_SIG_from_bytes(sig, sig_len);
1258ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (s == NULL) {
1268ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    goto err;
1278ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1288ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1298ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  /* Defend against potential laxness in the DER parser. */
1308ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  size_t der_len;
1318ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  if (!ECDSA_SIG_to_bytes(&der, &der_len, s) ||
1328ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan      der_len != sig_len || OPENSSL_memcmp(sig, der, sig_len) != 0) {
1338ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    /* This should never happen. crypto/bytestring is strictly DER. */
1348ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR);
1358ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan    goto err;
1368ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  }
1378ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1388ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ret = ECDSA_do_verify(digest, digest_len, s, eckey);
1398ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan
1408ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloanerr:
1418ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  OPENSSL_free(der);
1428ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  ECDSA_SIG_free(s);
1438ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan  return ret;
1448ff035535f7cf2903f02bbe94d2fa10b7ab855f1Robert Sloan}
145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
147d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t ECDSA_size(const EC_KEY *key) {
148b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (key == NULL) {
149b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
150b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
151d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
152b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t group_order_size;
153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  if (key->ecdsa_meth && key->ecdsa_meth->group_order_size) {
154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    group_order_size = key->ecdsa_meth->group_order_size(key);
155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  } else {
156b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    const EC_GROUP *group = EC_KEY_get0_group(key);
157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    if (group == NULL) {
158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley      return 0;
159d9e397b599b13d642138480a28c14db7a136bf0Adam Langley    }
160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
1614139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley    group_order_size = BN_num_bytes(EC_GROUP_get0_order(group));
162d9e397b599b13d642138480a28c14db7a136bf0Adam Langley  }
163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley
164b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ECDSA_SIG_max_len(group_order_size);
165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley}
166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley
167b8494591d1b1a143f3b192d845c238bbf3bc629dKenny RootECDSA_SIG *ECDSA_SIG_parse(CBS *cbs) {
168b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  ECDSA_SIG *ret = ECDSA_SIG_new();
169b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (ret == NULL) {
170b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return NULL;
171b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
172b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBS child;
173b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
1744969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !BN_parse_asn1_unsigned(&child, ret->r) ||
1754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !BN_parse_asn1_unsigned(&child, ret->s) ||
176b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      CBS_len(&child) != 0) {
177b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
178b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    ECDSA_SIG_free(ret);
179b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return NULL;
180b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
181b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ret;
182b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
183b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
184b8494591d1b1a143f3b192d845c238bbf3bc629dKenny RootECDSA_SIG *ECDSA_SIG_from_bytes(const uint8_t *in, size_t in_len) {
185b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBS cbs;
186b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBS_init(&cbs, in, in_len);
187b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs);
188b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (ret == NULL || CBS_len(&cbs) != 0) {
189b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
190b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    ECDSA_SIG_free(ret);
191b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return NULL;
192b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
193b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ret;
194b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
195b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
196b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootint ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig) {
197b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB child;
198b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
1994969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !BN_marshal_asn1(&child, sig->r) ||
2004969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !BN_marshal_asn1(&child, sig->s) ||
201b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      !CBB_flush(cbb)) {
202b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
203b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
204b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
205b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return 1;
206b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
207b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
208b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootint ECDSA_SIG_to_bytes(uint8_t **out_bytes, size_t *out_len,
209b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root                       const ECDSA_SIG *sig) {
210b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB cbb;
211b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBB_zero(&cbb);
212b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (!CBB_init(&cbb, 0) ||
213b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      !ECDSA_SIG_marshal(&cbb, sig) ||
214b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root      !CBB_finish(&cbb, out_bytes, out_len)) {
215b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
216b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    CBB_cleanup(&cbb);
217b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
218b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
219b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return 1;
220b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
221b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
222b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root/* der_len_len returns the number of bytes needed to represent a length of |len|
223b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root * in DER. */
224b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootstatic size_t der_len_len(size_t len) {
225b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (len < 0x80) {
226b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 1;
227b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
228b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t ret = 1;
229b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  while (len > 0) {
230b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    ret++;
231b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    len >>= 8;
232b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
233b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ret;
234b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
235b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
236b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootsize_t ECDSA_SIG_max_len(size_t order_len) {
237b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* Compute the maximum length of an |order_len| byte integer. Defensively
238b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root   * assume that the leading 0x00 is included. */
239b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len;
240b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (integer_len < order_len) {
241b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
242b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
243b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* An ECDSA signature is two INTEGERs. */
244b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t value_len = 2 * integer_len;
245b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (value_len < integer_len) {
246b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
247b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
248b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  /* Add the header. */
249b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len;
250b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (ret < value_len) {
251b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return 0;
252b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
253b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ret;
254b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
255b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
256b8494591d1b1a143f3b192d845c238bbf3bc629dKenny RootECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp, long len) {
257b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (len < 0) {
258b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return NULL;
259b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
260b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBS cbs;
261b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  CBS_init(&cbs, *inp, (size_t)len);
262b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  ECDSA_SIG *ret = ECDSA_SIG_parse(&cbs);
263b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (ret == NULL) {
264b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return NULL;
265b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
266b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  if (out != NULL) {
267b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    ECDSA_SIG_free(*out);
268b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    *out = ret;
269b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
2704969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  *inp = CBS_data(&cbs);
271b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  return ret;
272b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
273b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root
274b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Rootint i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) {
2754969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  CBB cbb;
2764969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  if (!CBB_init(&cbb, 0) ||
2774969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin      !ECDSA_SIG_marshal(&cbb, sig)) {
2784969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin    CBB_cleanup(&cbb);
279b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root    return -1;
280b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root  }
2814969cc9b0ab2905ec478277f50ed3849b37a6c6bDavid Benjamin  return CBB_finish_i2d(&cbb, outp);
282b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root}
283