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

Annotation of src/usr.bin/ssh/kexsntrup761x25519.c, Revision 1.1

1.1     ! djm         1: /* $OpenBSD: kexsntrup761x25519.c,v 1.4 2020/12/19 22:09:21 tobhe Exp $ */
        !             2: /*
        !             3:  * Copyright (c) 2019 Markus Friedl.  All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  *
        !            14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            15:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            16:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            17:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            18:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            19:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            20:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            21:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            22:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            23:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            24:  */
        !            25:
        !            26: #include <sys/types.h>
        !            27:
        !            28: #include <stdio.h>
        !            29: #include <string.h>
        !            30: #include <signal.h>
        !            31:
        !            32: #include "sshkey.h"
        !            33: #include "kex.h"
        !            34: #include "sshbuf.h"
        !            35: #include "digest.h"
        !            36: #include "ssherr.h"
        !            37:
        !            38: int
        !            39: kex_kem_sntrup761x25519_keypair(struct kex *kex)
        !            40: {
        !            41:        struct sshbuf *buf = NULL;
        !            42:        u_char *cp = NULL;
        !            43:        size_t need;
        !            44:        int r;
        !            45:
        !            46:        if ((buf = sshbuf_new()) == NULL)
        !            47:                return SSH_ERR_ALLOC_FAIL;
        !            48:        need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
        !            49:        if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
        !            50:                goto out;
        !            51:        crypto_kem_sntrup761_keypair(cp, kex->sntrup761_client_key);
        !            52: #ifdef DEBUG_KEXECDH
        !            53:        dump_digest("client public key sntrup761:", cp,
        !            54:            crypto_kem_sntrup761_PUBLICKEYBYTES);
        !            55: #endif
        !            56:        cp += crypto_kem_sntrup761_PUBLICKEYBYTES;
        !            57:        kexc25519_keygen(kex->c25519_client_key, cp);
        !            58: #ifdef DEBUG_KEXECDH
        !            59:        dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
        !            60: #endif
        !            61:        kex->client_pub = buf;
        !            62:        buf = NULL;
        !            63:  out:
        !            64:        sshbuf_free(buf);
        !            65:        return r;
        !            66: }
        !            67:
        !            68: int
        !            69: kex_kem_sntrup761x25519_enc(struct kex *kex,
        !            70:    const struct sshbuf *client_blob, struct sshbuf **server_blobp,
        !            71:    struct sshbuf **shared_secretp)
        !            72: {
        !            73:        struct sshbuf *server_blob = NULL;
        !            74:        struct sshbuf *buf = NULL;
        !            75:        const u_char *client_pub;
        !            76:        u_char *kem_key, *ciphertext, *server_pub;
        !            77:        u_char server_key[CURVE25519_SIZE];
        !            78:        u_char hash[SSH_DIGEST_MAX_LENGTH];
        !            79:        size_t need;
        !            80:        int r;
        !            81:
        !            82:        *server_blobp = NULL;
        !            83:        *shared_secretp = NULL;
        !            84:
        !            85:        /* client_blob contains both KEM and ECDH client pubkeys */
        !            86:        need = crypto_kem_sntrup761_PUBLICKEYBYTES + CURVE25519_SIZE;
        !            87:        if (sshbuf_len(client_blob) != need) {
        !            88:                r = SSH_ERR_SIGNATURE_INVALID;
        !            89:                goto out;
        !            90:        }
        !            91:        client_pub = sshbuf_ptr(client_blob);
        !            92: #ifdef DEBUG_KEXECDH
        !            93:        dump_digest("client public key sntrup761:", client_pub,
        !            94:            crypto_kem_sntrup761_PUBLICKEYBYTES);
        !            95:        dump_digest("client public key 25519:",
        !            96:            client_pub + crypto_kem_sntrup761_PUBLICKEYBYTES,
        !            97:            CURVE25519_SIZE);
        !            98: #endif
        !            99:        /* allocate buffer for concatenation of KEM key and ECDH shared key */
        !           100:        /* the buffer will be hashed and the result is the shared secret */
        !           101:        if ((buf = sshbuf_new()) == NULL) {
        !           102:                r = SSH_ERR_ALLOC_FAIL;
        !           103:                goto out;
        !           104:        }
        !           105:        if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
        !           106:            &kem_key)) != 0)
        !           107:                goto out;
        !           108:        /* allocate space for encrypted KEM key and ECDH pub key */
        !           109:        if ((server_blob = sshbuf_new()) == NULL) {
        !           110:                r = SSH_ERR_ALLOC_FAIL;
        !           111:                goto out;
        !           112:        }
        !           113:        need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
        !           114:        if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
        !           115:                goto out;
        !           116:        /* generate and encrypt KEM key with client key */
        !           117:        crypto_kem_sntrup761_enc(ciphertext, kem_key, client_pub);
        !           118:        /* generate ECDH key pair, store server pubkey after ciphertext */
        !           119:        server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
        !           120:        kexc25519_keygen(server_key, server_pub);
        !           121:        /* append ECDH shared key */
        !           122:        client_pub += crypto_kem_sntrup761_PUBLICKEYBYTES;
        !           123:        if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
        !           124:                goto out;
        !           125:        if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
        !           126:                goto out;
        !           127: #ifdef DEBUG_KEXECDH
        !           128:        dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
        !           129:        dump_digest("server cipher text:", ciphertext,
        !           130:            crypto_kem_sntrup761_CIPHERTEXTBYTES);
        !           131:        dump_digest("server kem key:", kem_key, sizeof(kem_key));
        !           132:        dump_digest("concatenation of KEM key and ECDH shared key:",
        !           133:            sshbuf_ptr(buf), sshbuf_len(buf));
        !           134: #endif
        !           135:        /* string-encoded hash is resulting shared secret */
        !           136:        sshbuf_reset(buf);
        !           137:        if ((r = sshbuf_put_string(buf, hash,
        !           138:            ssh_digest_bytes(kex->hash_alg))) != 0)
        !           139:                goto out;
        !           140: #ifdef DEBUG_KEXECDH
        !           141:        dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
        !           142: #endif
        !           143:        *server_blobp = server_blob;
        !           144:        *shared_secretp = buf;
        !           145:        server_blob = NULL;
        !           146:        buf = NULL;
        !           147:  out:
        !           148:        explicit_bzero(hash, sizeof(hash));
        !           149:        explicit_bzero(server_key, sizeof(server_key));
        !           150:        sshbuf_free(server_blob);
        !           151:        sshbuf_free(buf);
        !           152:        return r;
        !           153: }
        !           154:
        !           155: int
        !           156: kex_kem_sntrup761x25519_dec(struct kex *kex,
        !           157:     const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
        !           158: {
        !           159:        struct sshbuf *buf = NULL;
        !           160:        u_char *kem_key = NULL;
        !           161:        const u_char *ciphertext, *server_pub;
        !           162:        u_char hash[SSH_DIGEST_MAX_LENGTH];
        !           163:        size_t need;
        !           164:        int r, decoded;
        !           165:
        !           166:        *shared_secretp = NULL;
        !           167:
        !           168:        need = crypto_kem_sntrup761_CIPHERTEXTBYTES + CURVE25519_SIZE;
        !           169:        if (sshbuf_len(server_blob) != need) {
        !           170:                r = SSH_ERR_SIGNATURE_INVALID;
        !           171:                goto out;
        !           172:        }
        !           173:        ciphertext = sshbuf_ptr(server_blob);
        !           174:        server_pub = ciphertext + crypto_kem_sntrup761_CIPHERTEXTBYTES;
        !           175: #ifdef DEBUG_KEXECDH
        !           176:        dump_digest("server cipher text:", ciphertext,
        !           177:            crypto_kem_sntrup761_CIPHERTEXTBYTES);
        !           178:        dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
        !           179: #endif
        !           180:        /* hash concatenation of KEM key and ECDH shared key */
        !           181:        if ((buf = sshbuf_new()) == NULL) {
        !           182:                r = SSH_ERR_ALLOC_FAIL;
        !           183:                goto out;
        !           184:        }
        !           185:        if ((r = sshbuf_reserve(buf, crypto_kem_sntrup761_BYTES,
        !           186:            &kem_key)) != 0)
        !           187:                goto out;
        !           188:        decoded = crypto_kem_sntrup761_dec(kem_key, ciphertext,
        !           189:            kex->sntrup761_client_key);
        !           190:        if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
        !           191:            buf, 1)) < 0)
        !           192:                goto out;
        !           193:        if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
        !           194:                goto out;
        !           195: #ifdef DEBUG_KEXECDH
        !           196:        dump_digest("client kem key:", kem_key, crypto_kem_sntrup761_BYTES);
        !           197:        dump_digest("concatenation of KEM key and ECDH shared key:",
        !           198:            sshbuf_ptr(buf), sshbuf_len(buf));
        !           199: #endif
        !           200:        sshbuf_reset(buf);
        !           201:        if ((r = sshbuf_put_string(buf, hash,
        !           202:            ssh_digest_bytes(kex->hash_alg))) != 0)
        !           203:                goto out;
        !           204: #ifdef DEBUG_KEXECDH
        !           205:        dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
        !           206: #endif
        !           207:        if (decoded != 0) {
        !           208:                r = SSH_ERR_SIGNATURE_INVALID;
        !           209:                goto out;
        !           210:        }
        !           211:        *shared_secretp = buf;
        !           212:        buf = NULL;
        !           213:  out:
        !           214:        explicit_bzero(hash, sizeof(hash));
        !           215:        sshbuf_free(buf);
        !           216:        return r;
        !           217: }