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

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

1.1     ! djm         1: /* $OpenBSD: $ */
        !             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_sntrup4591761x25519_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_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
        !            49:        if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
        !            50:                goto out;
        !            51:        crypto_kem_sntrup4591761_keypair(cp, kex->sntrup4591761_client_key);
        !            52: #ifdef DEBUG_KEXECDH
        !            53:        dump_digest("client public key sntrup4591761:", cp,
        !            54:            crypto_kem_sntrup4591761_PUBLICKEYBYTES);
        !            55: #endif
        !            56:        cp += crypto_kem_sntrup4591761_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->kem_client_pub = buf;
        !            62:        buf = NULL;
        !            63:  out:
        !            64:        sshbuf_free(buf);
        !            65:        return r;
        !            66: }
        !            67:
        !            68: int
        !            69: kex_kem_sntrup4591761x25519_enc(struct kex *kex, const u_char *pkblob,
        !            70:    size_t pklen, struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
        !            71: {
        !            72:        struct sshbuf *server_blob = NULL;
        !            73:        struct sshbuf *buf = NULL;
        !            74:        u_char *kem_key, *ciphertext, *server_pub;
        !            75:        u_char server_key[CURVE25519_SIZE];
        !            76:        u_char hash[SSH_DIGEST_MAX_LENGTH];
        !            77:        size_t need;
        !            78:        int r;
        !            79:
        !            80:        *server_blobp = NULL;
        !            81:        *shared_secretp = NULL;
        !            82:
        !            83:        /* pkblob contains both KEM and ECDH client pubkeys */
        !            84:        need = crypto_kem_sntrup4591761_PUBLICKEYBYTES + CURVE25519_SIZE;
        !            85:        if (pklen != need) {
        !            86:                r = SSH_ERR_SIGNATURE_INVALID;
        !            87:                goto out;
        !            88:        }
        !            89: #ifdef DEBUG_KEXECDH
        !            90:        dump_digest("client public key sntrup4591761:", pkblob,
        !            91:            crypto_kem_sntrup4591761_PUBLICKEYBYTES);
        !            92:        dump_digest("client public key 25519:",
        !            93:            pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, CURVE25519_SIZE);
        !            94: #endif
        !            95:        /* allocate buffer for concatenation of KEM key and ECDH shared key */
        !            96:        /* the buffer will be hashed and the result is the shared secret */
        !            97:        if ((buf = sshbuf_new()) == NULL) {
        !            98:                r = SSH_ERR_ALLOC_FAIL;
        !            99:                goto out;
        !           100:        }
        !           101:        if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
        !           102:            &kem_key)) != 0)
        !           103:                goto out;
        !           104:        /* allocate space for encrypted KEM key and ECDH pub key */
        !           105:        if ((server_blob = sshbuf_new()) == NULL) {
        !           106:                r = SSH_ERR_ALLOC_FAIL;
        !           107:                goto out;
        !           108:        }
        !           109:        need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
        !           110:        if ((r = sshbuf_reserve(server_blob, need, &ciphertext)) != 0)
        !           111:                goto out;
        !           112:        /* generate and encrypt KEM key with client key */
        !           113:        crypto_kem_sntrup4591761_enc(ciphertext, kem_key, pkblob);
        !           114:        /* generate ECDH key pair, store server pubkey after ciphertext */
        !           115:        server_pub = ciphertext + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
        !           116:        kexc25519_keygen(server_key, server_pub);
        !           117:        /* append ECDH shared key */
        !           118:        if ((r = kexc25519_shared_key_ext(server_key,
        !           119:            pkblob + crypto_kem_sntrup4591761_PUBLICKEYBYTES, buf, 1)) < 0)
        !           120:                goto out;
        !           121:        if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
        !           122:                goto out;
        !           123: #ifdef DEBUG_KEXECDH
        !           124:        dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
        !           125:        dump_digest("server cipher text:", ciphertext,
        !           126:            crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
        !           127:        dump_digest("server kem key:", kem_key, sizeof(kem_key));
        !           128:        dump_digest("concatenation of KEM key and ECDH shared key:",
        !           129:            sshbuf_ptr(buf), sshbuf_len(buf));
        !           130: #endif
        !           131:        /* string-encoded hash is resulting shared secret */
        !           132:        sshbuf_reset(buf);
        !           133:        if ((r = sshbuf_put_string(buf, hash,
        !           134:            ssh_digest_bytes(kex->hash_alg))) != 0)
        !           135:                goto out;
        !           136: #ifdef DEBUG_KEXECDH
        !           137:        dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
        !           138: #endif
        !           139:        *server_blobp = server_blob;
        !           140:        *shared_secretp = buf;
        !           141:        server_blob = NULL;
        !           142:        buf = NULL;
        !           143:  out:
        !           144:        explicit_bzero(hash, sizeof(hash));
        !           145:        explicit_bzero(server_key, sizeof(server_key));
        !           146:        sshbuf_free(server_blob);
        !           147:        sshbuf_free(buf);
        !           148:        return r;
        !           149: }
        !           150:
        !           151: int
        !           152: kex_kem_sntrup4591761x25519_dec(struct kex *kex, const u_char *pkblob,
        !           153:     size_t pklen, struct sshbuf **shared_secretp)
        !           154: {
        !           155:        struct sshbuf *buf = NULL;
        !           156:        u_char *kem_key = NULL;
        !           157:        const u_char *ciphertext, *server_pub;
        !           158:        u_char hash[SSH_DIGEST_MAX_LENGTH];
        !           159:        size_t need;
        !           160:        int r, decoded;
        !           161:
        !           162:        *shared_secretp = NULL;
        !           163:
        !           164:        need = crypto_kem_sntrup4591761_CIPHERTEXTBYTES + CURVE25519_SIZE;
        !           165:        if (pklen != need) {
        !           166:                r = SSH_ERR_SIGNATURE_INVALID;
        !           167:                goto out;
        !           168:        }
        !           169:        ciphertext = pkblob;
        !           170:        server_pub = pkblob + crypto_kem_sntrup4591761_CIPHERTEXTBYTES;
        !           171: #ifdef DEBUG_KEXECDH
        !           172:        dump_digest("server cipher text:", ciphertext,
        !           173:            crypto_kem_sntrup4591761_CIPHERTEXTBYTES);
        !           174:        dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
        !           175: #endif
        !           176:        /* hash concatenation of KEM key and ECDH shared key */
        !           177:        if ((buf = sshbuf_new()) == NULL) {
        !           178:                r = SSH_ERR_ALLOC_FAIL;
        !           179:                goto out;
        !           180:        }
        !           181:        if ((r = sshbuf_reserve(buf, crypto_kem_sntrup4591761_BYTES,
        !           182:            &kem_key)) != 0)
        !           183:                goto out;
        !           184:        decoded = crypto_kem_sntrup4591761_dec(kem_key, ciphertext,
        !           185:            kex->sntrup4591761_client_key);
        !           186:        if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
        !           187:            buf, 1)) < 0)
        !           188:                goto out;
        !           189:        if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
        !           190:                goto out;
        !           191: #ifdef DEBUG_KEXECDH
        !           192:        dump_digest("client kem key:", kem_key, sizeof(kem_key));
        !           193:        dump_digest("concatenation of KEM key and ECDH shared key:",
        !           194:            sshbuf_ptr(buf), sshbuf_len(buf));
        !           195: #endif
        !           196:        sshbuf_reset(buf);
        !           197:        if ((r = sshbuf_put_string(buf, hash,
        !           198:            ssh_digest_bytes(kex->hash_alg))) != 0)
        !           199:                goto out;
        !           200: #ifdef DEBUG_KEXECDH
        !           201:        dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
        !           202: #endif
        !           203:        if (decoded != 0) {
        !           204:                r = SSH_ERR_SIGNATURE_INVALID;
        !           205:                goto out;
        !           206:        }
        !           207:        *shared_secretp = buf;
        !           208:        buf = NULL;
        !           209:  out:
        !           210:        explicit_bzero(hash, sizeof(hash));
        !           211:        sshbuf_free(buf);
        !           212:        return r;
        !           213: }