[BACK]Return to bufec.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/bufec.c, Revision 1.3

1.3     ! tedu        1: /* $OpenBSD: bufec.c,v 1.2 2013/05/17 00:13:13 djm Exp $ */
1.1       djm         2: /*
                      3:  * Copyright (c) 2010 Damien Miller <djm@mindrot.org>
                      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 <sys/types.h>
                     18:
                     19: #include <openssl/bn.h>
                     20: #include <openssl/ec.h>
                     21:
                     22: #include <string.h>
                     23: #include <stdarg.h>
                     24:
                     25: #include "xmalloc.h"
                     26: #include "buffer.h"
                     27: #include "log.h"
                     28: #include "misc.h"
                     29:
                     30: /*
                     31:  * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed
                     32:  * encoding represents this as two bitstring points that should each
                     33:  * be no longer than the field length, SEC1 specifies a 1 byte
                     34:  * point type header.
                     35:  * Being paranoid here may insulate us to parsing problems in
                     36:  * EC_POINT_oct2point.
                     37:  */
                     38: #define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1)
                     39:
                     40: /*
                     41:  * Append an EC_POINT to the buffer as a string containing a SEC1 encoded
                     42:  * uncompressed point. Fortunately OpenSSL handles the gory details for us.
                     43:  */
                     44: int
                     45: buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
                     46:     const EC_POINT *point)
                     47: {
                     48:        u_char *buf = NULL;
                     49:        size_t len;
                     50:        BN_CTX *bnctx;
                     51:        int ret = -1;
                     52:
                     53:        /* Determine length */
                     54:        if ((bnctx = BN_CTX_new()) == NULL)
                     55:                fatal("%s: BN_CTX_new failed", __func__);
                     56:        len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
                     57:            NULL, 0, bnctx);
                     58:        if (len > BUFFER_MAX_ECPOINT_LEN) {
                     59:                error("%s: giant EC point: len = %lu (max %u)",
                     60:                    __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
                     61:                goto out;
                     62:        }
                     63:        /* Convert */
                     64:        buf = xmalloc(len);
                     65:        if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
                     66:            buf, len, bnctx) != len) {
                     67:                error("%s: EC_POINT_point2oct length mismatch", __func__);
                     68:                goto out;
                     69:        }
                     70:        /* Append */
                     71:        buffer_put_string(buffer, buf, len);
                     72:        ret = 0;
                     73:  out:
                     74:        if (buf != NULL) {
1.3     ! tedu       75:                explicit_bzero(buf, len);
1.2       djm        76:                free(buf);
1.1       djm        77:        }
                     78:        BN_CTX_free(bnctx);
                     79:        return ret;
                     80: }
                     81:
                     82: void
                     83: buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
                     84:     const EC_POINT *point)
                     85: {
                     86:        if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
                     87:                fatal("%s: buffer error", __func__);
                     88: }
                     89:
                     90: int
                     91: buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
                     92:     EC_POINT *point)
                     93: {
                     94:        u_char *buf;
                     95:        u_int len;
                     96:        BN_CTX *bnctx;
                     97:        int ret = -1;
                     98:
                     99:        if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
                    100:                error("%s: invalid point", __func__);
                    101:                return -1;
                    102:        }
                    103:        if ((bnctx = BN_CTX_new()) == NULL)
                    104:                fatal("%s: BN_CTX_new failed", __func__);
                    105:        if (len > BUFFER_MAX_ECPOINT_LEN) {
                    106:                error("%s: EC_POINT too long: %u > max %u", __func__,
                    107:                    len, BUFFER_MAX_ECPOINT_LEN);
                    108:                goto out;
                    109:        }
                    110:        if (len == 0) {
                    111:                error("%s: EC_POINT buffer is empty", __func__);
                    112:                goto out;
                    113:        }
                    114:        if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
                    115:                error("%s: EC_POINT is in an incorrect form: "
                    116:                    "0x%02x (want 0x%02x)", __func__, buf[0],
                    117:                    POINT_CONVERSION_UNCOMPRESSED);
                    118:                goto out;
                    119:        }
                    120:        if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
                    121:                error("buffer_get_bignum2_ret: BN_bin2bn failed");
                    122:                goto out;
                    123:        }
                    124:        /* EC_POINT_oct2point verifies that the point is on the curve for us */
                    125:        ret = 0;
                    126:  out:
                    127:        BN_CTX_free(bnctx);
1.3     ! tedu      128:        explicit_bzero(buf, len);
1.2       djm       129:        free(buf);
1.1       djm       130:        return ret;
                    131: }
                    132:
                    133: void
                    134: buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
                    135:     EC_POINT *point)
                    136: {
                    137:        if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
                    138:                fatal("%s: buffer error", __func__);
                    139: }
                    140: