LCOV - code coverage report
Current view: top level - openssh-6.6p1 - ssh-ecdsa.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 54 78 69.2 %
Date: 2014-08-01 Functions: 2 2 100.0 %
Branches: 18 38 47.4 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
       4                 :            :  * Copyright (c) 2010 Damien Miller.  All rights reserved.
       5                 :            :  *
       6                 :            :  * Redistribution and use in source and binary forms, with or without
       7                 :            :  * modification, are permitted provided that the following conditions
       8                 :            :  * are met:
       9                 :            :  * 1. Redistributions of source code must retain the above copyright
      10                 :            :  *    notice, this list of conditions and the following disclaimer.
      11                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      12                 :            :  *    notice, this list of conditions and the following disclaimer in the
      13                 :            :  *    documentation and/or other materials provided with the distribution.
      14                 :            :  *
      15                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      16                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      17                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      18                 :            :  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
      19                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      20                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      21                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      22                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      23                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      24                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      25                 :            :  */
      26                 :            : 
      27                 :            : #include "includes.h"
      28                 :            : 
      29                 :            : #ifdef OPENSSL_HAS_ECC
      30                 :            : 
      31                 :            : #include <sys/types.h>
      32                 :            : 
      33                 :            : #include <openssl/bn.h>
      34                 :            : #include <openssl/ec.h>
      35                 :            : #include <openssl/ecdsa.h>
      36                 :            : #include <openssl/evp.h>
      37                 :            : 
      38                 :            : #include <string.h>
      39                 :            : 
      40                 :            : #include "xmalloc.h"
      41                 :            : #include "buffer.h"
      42                 :            : #include "compat.h"
      43                 :            : #include "log.h"
      44                 :            : #include "key.h"
      45                 :            : #include "digest.h"
      46                 :            : 
      47                 :            : int
      48                 :         84 : ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp,
      49                 :            :     const u_char *data, u_int datalen)
      50                 :            : {
      51                 :            :         ECDSA_SIG *sig;
      52                 :            :         int hash_alg;
      53                 :            :         u_char digest[SSH_DIGEST_MAX_LENGTH];
      54                 :            :         u_int len, dlen;
      55                 :            :         Buffer b, bb;
      56                 :            : 
      57 [ +  - ][ +  - ]:         84 :         if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
                 [ -  + ]
      58                 :         84 :             key->ecdsa == NULL) {
      59                 :          0 :                 error("%s: no ECDSA key", __func__);
      60                 :          0 :                 return -1;
      61                 :            :         }
      62                 :            : 
      63                 :         84 :         hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
      64         [ -  + ]:         84 :         if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
      65                 :          0 :                 error("%s: bad hash algorithm %d", __func__, hash_alg);
      66                 :          0 :                 return -1;
      67                 :            :         }
      68         [ -  + ]:         84 :         if (ssh_digest_memory(hash_alg, data, datalen,
      69                 :            :             digest, sizeof(digest)) != 0) {
      70                 :          0 :                 error("%s: digest_memory failed", __func__);
      71                 :          0 :                 return -1;
      72                 :            :         }
      73                 :            : 
      74                 :         84 :         sig = ECDSA_do_sign(digest, dlen, key->ecdsa);
      75                 :         84 :         explicit_bzero(digest, sizeof(digest));
      76                 :            : 
      77         [ -  + ]:         84 :         if (sig == NULL) {
      78                 :          0 :                 error("%s: sign failed", __func__);
      79                 :          0 :                 return -1;
      80                 :            :         }
      81                 :            : 
      82                 :         84 :         buffer_init(&bb);
      83                 :         84 :         buffer_put_bignum2(&bb, sig->r);
      84                 :         84 :         buffer_put_bignum2(&bb, sig->s);
      85                 :         84 :         ECDSA_SIG_free(sig);
      86                 :            : 
      87                 :         84 :         buffer_init(&b);
      88                 :         84 :         buffer_put_cstring(&b, key_ssh_name_plain(key));
      89                 :         84 :         buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
      90                 :         84 :         buffer_free(&bb);
      91                 :         84 :         len = buffer_len(&b);
      92         [ +  - ]:         84 :         if (lenp != NULL)
      93                 :         84 :                 *lenp = len;
      94         [ +  - ]:         84 :         if (sigp != NULL) {
      95                 :         84 :                 *sigp = xmalloc(len);
      96                 :         84 :                 memcpy(*sigp, buffer_ptr(&b), len);
      97                 :            :         }
      98                 :         84 :         buffer_free(&b);
      99                 :            : 
     100                 :         84 :         return 0;
     101                 :            : }
     102                 :            : int
     103                 :        324 : ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
     104                 :            :     const u_char *data, u_int datalen)
     105                 :            : {
     106                 :            :         ECDSA_SIG *sig;
     107                 :            :         int hash_alg;
     108                 :            :         u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
     109                 :            :         u_int len, dlen;
     110                 :            :         int rlen, ret;
     111                 :            :         Buffer b, bb;
     112                 :            :         char *ktype;
     113                 :            : 
     114 [ +  - ][ +  - ]:        324 :         if (key == NULL || key_type_plain(key->type) != KEY_ECDSA ||
                 [ -  + ]
     115                 :        324 :             key->ecdsa == NULL) {
     116                 :          0 :                 error("%s: no ECDSA key", __func__);
     117                 :          0 :                 return -1;
     118                 :            :         }
     119                 :            : 
     120                 :            :         /* fetch signature */
     121                 :        324 :         buffer_init(&b);
     122                 :        324 :         buffer_append(&b, signature, signaturelen);
     123                 :        324 :         ktype = buffer_get_string(&b, NULL);
     124         [ -  + ]:        324 :         if (strcmp(key_ssh_name_plain(key), ktype) != 0) {
     125                 :          0 :                 error("%s: cannot handle type %s", __func__, ktype);
     126                 :          0 :                 buffer_free(&b);
     127                 :          0 :                 free(ktype);
     128                 :          0 :                 return -1;
     129                 :            :         }
     130                 :        324 :         free(ktype);
     131                 :        324 :         sigblob = buffer_get_string(&b, &len);
     132                 :        324 :         rlen = buffer_len(&b);
     133                 :        324 :         buffer_free(&b);
     134         [ -  + ]:        324 :         if (rlen != 0) {
     135                 :          0 :                 error("%s: remaining bytes in signature %d", __func__, rlen);
     136                 :          0 :                 free(sigblob);
     137                 :          0 :                 return -1;
     138                 :            :         }
     139                 :            : 
     140                 :            :         /* parse signature */
     141         [ -  + ]:        324 :         if ((sig = ECDSA_SIG_new()) == NULL)
     142                 :          0 :                 fatal("%s: ECDSA_SIG_new failed", __func__);
     143                 :            : 
     144                 :        324 :         buffer_init(&bb);
     145                 :        324 :         buffer_append(&bb, sigblob, len);
     146                 :        324 :         buffer_get_bignum2(&bb, sig->r);
     147                 :        324 :         buffer_get_bignum2(&bb, sig->s);
     148         [ -  + ]:        324 :         if (buffer_len(&bb) != 0)
     149                 :          0 :                 fatal("%s: remaining bytes in inner sigblob", __func__);
     150                 :        324 :         buffer_free(&bb);
     151                 :            : 
     152                 :            :         /* clean up */
     153                 :        324 :         explicit_bzero(sigblob, len);
     154                 :        324 :         free(sigblob);
     155                 :            : 
     156                 :            :         /* hash the data */
     157                 :        324 :         hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
     158         [ -  + ]:        324 :         if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
     159                 :          0 :                 error("%s: bad hash algorithm %d", __func__, hash_alg);
     160                 :          0 :                 return -1;
     161                 :            :         }
     162         [ -  + ]:        324 :         if (ssh_digest_memory(hash_alg, data, datalen,
     163                 :            :             digest, sizeof(digest)) != 0) {
     164                 :          0 :                 error("%s: digest_memory failed", __func__);
     165                 :          0 :                 return -1;
     166                 :            :         }
     167                 :            : 
     168                 :        324 :         ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa);
     169                 :        324 :         explicit_bzero(digest, sizeof(digest));
     170                 :            : 
     171                 :        324 :         ECDSA_SIG_free(sig);
     172                 :            : 
     173         [ -  + ]:        324 :         debug("%s: signature %s", __func__,
     174         [ #  # ]:          0 :             ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error");
     175                 :        324 :         return ret;
     176                 :            : }
     177                 :            : 
     178                 :            : #endif /* OPENSSL_HAS_ECC */

Generated by: LCOV version 1.9