LCOV - code coverage report
Current view: top level - openssh-6.6p1 - ssh-rsa.c (source / functions) Hit Total Coverage
Test: lcov_coverage_final.info Lines: 73 127 57.5 %
Date: 2014-08-01 Functions: 3 3 100.0 %
Branches: 29 58 50.0 %

           Branch data     Line data    Source code
       1                 :            : /* $OpenBSD: ssh-rsa.c,v 1.51 2014/02/02 03:44:31 djm Exp $ */
       2                 :            : /*
       3                 :            :  * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.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                 :            : 
      18                 :            : #include "includes.h"
      19                 :            : 
      20                 :            : #include <sys/types.h>
      21                 :            : 
      22                 :            : #include <openssl/evp.h>
      23                 :            : #include <openssl/err.h>
      24                 :            : 
      25                 :            : #include <stdarg.h>
      26                 :            : #include <string.h>
      27                 :            : 
      28                 :            : #include "xmalloc.h"
      29                 :            : #include "log.h"
      30                 :            : #include "buffer.h"
      31                 :            : #include "key.h"
      32                 :            : #include "compat.h"
      33                 :            : #include "misc.h"
      34                 :            : #include "ssh.h"
      35                 :            : #include "digest.h"
      36                 :            : 
      37                 :            : static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *);
      38                 :            : 
      39                 :            : /* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
      40                 :            : int
      41                 :       1361 : ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp,
      42                 :            :     const u_char *data, u_int datalen)
      43                 :            : {
      44                 :            :         int hash_alg;
      45                 :            :         u_char digest[SSH_DIGEST_MAX_LENGTH], *sig;
      46                 :            :         u_int slen, dlen, len;
      47                 :            :         int ok, nid;
      48                 :            :         Buffer b;
      49                 :            : 
      50 [ +  - ][ +  - ]:       1361 :         if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
                 [ -  + ]
      51                 :       1361 :             key->rsa == NULL) {
      52                 :          0 :                 error("%s: no RSA key", __func__);
      53                 :          0 :                 return -1;
      54                 :            :         }
      55                 :            : 
      56                 :            :         /* hash the data */
      57                 :       1361 :         hash_alg = SSH_DIGEST_SHA1;
      58                 :       1361 :         nid = NID_sha1;
      59         [ -  + ]:       1361 :         if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
      60                 :          0 :                 error("%s: bad hash algorithm %d", __func__, hash_alg);
      61                 :          0 :                 return -1;
      62                 :            :         }
      63         [ -  + ]:       1361 :         if (ssh_digest_memory(hash_alg, data, datalen,
      64                 :            :             digest, sizeof(digest)) != 0) {
      65                 :          0 :                 error("%s: ssh_digest_memory failed", __func__);
      66                 :          0 :                 return -1;
      67                 :            :         }
      68                 :            : 
      69                 :       1361 :         slen = RSA_size(key->rsa);
      70                 :       1361 :         sig = xmalloc(slen);
      71                 :            : 
      72                 :       1361 :         ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
      73                 :       1361 :         explicit_bzero(digest, sizeof(digest));
      74                 :            : 
      75         [ -  + ]:       1361 :         if (ok != 1) {
      76                 :          0 :                 int ecode = ERR_get_error();
      77                 :            : 
      78                 :          0 :                 error("%s: RSA_sign failed: %s", __func__,
      79                 :            :                     ERR_error_string(ecode, NULL));
      80                 :          0 :                 free(sig);
      81                 :          0 :                 return -1;
      82                 :            :         }
      83         [ -  + ]:       1361 :         if (len < slen) {
      84                 :          0 :                 u_int diff = slen - len;
      85                 :          0 :                 debug("slen %u > len %u", slen, len);
      86                 :          0 :                 memmove(sig + diff, sig, len);
      87                 :          0 :                 explicit_bzero(sig, diff);
      88         [ -  + ]:       1361 :         } else if (len > slen) {
      89                 :          0 :                 error("%s: slen %u slen2 %u", __func__, slen, len);
      90                 :          0 :                 free(sig);
      91                 :          0 :                 return -1;
      92                 :            :         }
      93                 :            :         /* encode signature */
      94                 :       1361 :         buffer_init(&b);
      95                 :       1361 :         buffer_put_cstring(&b, "ssh-rsa");
      96                 :       1361 :         buffer_put_string(&b, sig, slen);
      97                 :       1361 :         len = buffer_len(&b);
      98         [ +  - ]:       1361 :         if (lenp != NULL)
      99                 :       1361 :                 *lenp = len;
     100         [ +  - ]:       1361 :         if (sigp != NULL) {
     101                 :       1361 :                 *sigp = xmalloc(len);
     102                 :       1361 :                 memcpy(*sigp, buffer_ptr(&b), len);
     103                 :            :         }
     104                 :       1361 :         buffer_free(&b);
     105                 :       1361 :         explicit_bzero(sig, slen);
     106                 :       1361 :         free(sig);
     107                 :            : 
     108                 :       1361 :         return 0;
     109                 :            : }
     110                 :            : 
     111                 :            : int
     112                 :       2635 : ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen,
     113                 :            :     const u_char *data, u_int datalen)
     114                 :            : {
     115                 :            :         Buffer b;
     116                 :            :         int hash_alg;
     117                 :            :         char *ktype;
     118                 :            :         u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob;
     119                 :            :         u_int len, dlen, modlen;
     120                 :            :         int rlen, ret;
     121                 :            : 
     122 [ +  - ][ +  - ]:       2635 :         if (key == NULL || key_type_plain(key->type) != KEY_RSA ||
                 [ -  + ]
     123                 :       2635 :             key->rsa == NULL) {
     124                 :          0 :                 error("%s: no RSA key", __func__);
     125                 :          0 :                 return -1;
     126                 :            :         }
     127                 :            : 
     128         [ -  + ]:       2635 :         if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
     129                 :          0 :                 error("%s: RSA modulus too small: %d < minimum %d bits",
     130                 :          0 :                     __func__, BN_num_bits(key->rsa->n),
     131                 :            :                     SSH_RSA_MINIMUM_MODULUS_SIZE);
     132                 :          0 :                 return -1;
     133                 :            :         }
     134                 :       2635 :         buffer_init(&b);
     135                 :       2635 :         buffer_append(&b, signature, signaturelen);
     136                 :       2635 :         ktype = buffer_get_cstring(&b, NULL);
     137         [ -  + ]:       2635 :         if (strcmp("ssh-rsa", ktype) != 0) {
     138                 :          0 :                 error("%s: cannot handle type %s", __func__, ktype);
     139                 :          0 :                 buffer_free(&b);
     140                 :          0 :                 free(ktype);
     141                 :          0 :                 return -1;
     142                 :            :         }
     143                 :       2635 :         free(ktype);
     144                 :       2635 :         sigblob = buffer_get_string(&b, &len);
     145                 :       2635 :         rlen = buffer_len(&b);
     146                 :       2635 :         buffer_free(&b);
     147         [ -  + ]:       2635 :         if (rlen != 0) {
     148                 :          0 :                 error("%s: remaining bytes in signature %d", __func__, rlen);
     149                 :          0 :                 free(sigblob);
     150                 :          0 :                 return -1;
     151                 :            :         }
     152                 :            :         /* RSA_verify expects a signature of RSA_size */
     153                 :       2635 :         modlen = RSA_size(key->rsa);
     154         [ -  + ]:       2635 :         if (len > modlen) {
     155                 :          0 :                 error("%s: len %u > modlen %u", __func__, len, modlen);
     156                 :          0 :                 free(sigblob);
     157                 :          0 :                 return -1;
     158         [ -  + ]:       2635 :         } else if (len < modlen) {
     159                 :          0 :                 u_int diff = modlen - len;
     160                 :          0 :                 debug("%s: add padding: modlen %u > len %u", __func__,
     161                 :            :                     modlen, len);
     162                 :          0 :                 sigblob = xrealloc(sigblob, 1, modlen);
     163                 :          0 :                 memmove(sigblob + diff, sigblob, len);
     164                 :          0 :                 explicit_bzero(sigblob, diff);
     165                 :          0 :                 len = modlen;
     166                 :            :         }
     167                 :            :         /* hash the data */
     168                 :       2635 :         hash_alg = SSH_DIGEST_SHA1;
     169         [ -  + ]:       2635 :         if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
     170                 :          0 :                 error("%s: bad hash algorithm %d", __func__, hash_alg);
     171                 :          0 :                 return -1;
     172                 :            :         }
     173         [ -  + ]:       2635 :         if (ssh_digest_memory(hash_alg, data, datalen,
     174                 :            :             digest, sizeof(digest)) != 0) {
     175                 :          0 :                 error("%s: ssh_digest_memory failed", __func__);
     176                 :          0 :                 return -1;
     177                 :            :         }
     178                 :            : 
     179                 :       2635 :         ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
     180                 :            :             key->rsa);
     181                 :       2635 :         explicit_bzero(digest, sizeof(digest));
     182                 :       2635 :         explicit_bzero(sigblob, len);
     183                 :       2635 :         free(sigblob);
     184         [ +  - ]:       2635 :         debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : "");
     185                 :       2635 :         return ret;
     186                 :            : }
     187                 :            : 
     188                 :            : /*
     189                 :            :  * See:
     190                 :            :  * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
     191                 :            :  * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn
     192                 :            :  */
     193                 :            : /*
     194                 :            :  * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
     195                 :            :  *      oiw(14) secsig(3) algorithms(2) 26 }
     196                 :            :  */
     197                 :            : static const u_char id_sha1[] = {
     198                 :            :         0x30, 0x21, /* type Sequence, length 0x21 (33) */
     199                 :            :         0x30, 0x09, /* type Sequence, length 0x09 */
     200                 :            :         0x06, 0x05, /* type OID, length 0x05 */
     201                 :            :         0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */
     202                 :            :         0x05, 0x00, /* NULL */
     203                 :            :         0x04, 0x14  /* Octet string, length 0x14 (20), followed by sha1 hash */
     204                 :            : };
     205                 :            : 
     206                 :            : static int
     207                 :       2635 : openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen,
     208                 :            :     u_char *sigbuf, u_int siglen, RSA *rsa)
     209                 :            : {
     210                 :       2635 :         u_int ret, rsasize, oidlen = 0, hlen = 0;
     211                 :            :         int len, oidmatch, hashmatch;
     212                 :       2635 :         const u_char *oid = NULL;
     213                 :       2635 :         u_char *decrypted = NULL;
     214                 :            : 
     215                 :       2635 :         ret = 0;
     216         [ +  - ]:       2635 :         switch (hash_alg) {
     217                 :            :         case SSH_DIGEST_SHA1:
     218                 :       2635 :                 oid = id_sha1;
     219                 :       2635 :                 oidlen = sizeof(id_sha1);
     220                 :       2635 :                 hlen = 20;
     221                 :            :                 break;
     222                 :            :         default:
     223                 :            :                 goto done;
     224                 :            :         }
     225         [ -  + ]:       2635 :         if (hashlen != hlen) {
     226                 :          0 :                 error("bad hashlen");
     227                 :          0 :                 goto done;
     228                 :            :         }
     229                 :       2635 :         rsasize = RSA_size(rsa);
     230         [ -  + ]:       2635 :         if (siglen == 0 || siglen > rsasize) {
     231                 :          0 :                 error("bad siglen");
     232                 :          0 :                 goto done;
     233                 :            :         }
     234                 :       2635 :         decrypted = xmalloc(rsasize);
     235         [ -  + ]:       2635 :         if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
     236                 :            :             RSA_PKCS1_PADDING)) < 0) {
     237                 :          0 :                 error("RSA_public_decrypt failed: %s",
     238                 :            :                     ERR_error_string(ERR_get_error(), NULL));
     239                 :          0 :                 goto done;
     240                 :            :         }
     241 [ +  - ][ -  + ]:       2635 :         if (len < 0 || (u_int)len != hlen + oidlen) {
     242                 :          0 :                 error("bad decrypted len: %d != %d + %d", len, hlen, oidlen);
     243                 :          0 :                 goto done;
     244                 :            :         }
     245                 :       2635 :         oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
     246                 :       2635 :         hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
     247         [ -  + ]:       2635 :         if (!oidmatch) {
     248                 :          0 :                 error("oid mismatch");
     249                 :          0 :                 goto done;
     250                 :            :         }
     251         [ -  + ]:       2635 :         if (!hashmatch) {
     252                 :          0 :                 error("hash mismatch");
     253                 :          0 :                 goto done;
     254                 :            :         }
     255                 :            :         ret = 1;
     256                 :            : done:
     257                 :       2635 :         free(decrypted);
     258                 :       2635 :         return ret;
     259                 :            : }

Generated by: LCOV version 1.9