LCOV - code coverage report
Current view: top level - third_party/openssl/crypto/rsa - rsa_oaep.c (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 0 99 0.0 %
Date: 2015-10-10 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* crypto/rsa/rsa_oaep.c */
       2             : /*
       3             :  * Written by Ulf Moeller. This software is distributed on an "AS IS" basis,
       4             :  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
       5             :  */
       6             : 
       7             : /* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
       8             : 
       9             : /*
      10             :  * See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL:
      11             :  * http://www.shoup.net/papers/oaep.ps.Z> for problems with the security
      12             :  * proof for the original OAEP scheme, which EME-OAEP is based on. A new
      13             :  * proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern,
      14             :  * "RSA-OEAP is Still Alive!", Dec. 2000, <URL:
      15             :  * http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements
      16             :  * for the underlying permutation: "partial-one-wayness" instead of
      17             :  * one-wayness.  For the RSA function, this is an equivalent notion.
      18             :  */
      19             : 
      20             : #include "constant_time_locl.h"
      21             : 
      22             : #if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
      23             : # include <stdio.h>
      24             : # include "cryptlib.h"
      25             : # include <openssl/bn.h>
      26             : # include <openssl/rsa.h>
      27             : # include <openssl/evp.h>
      28             : # include <openssl/rand.h>
      29             : # include <openssl/sha.h>
      30             : 
      31           0 : int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
      32             :                                const unsigned char *from, int flen,
      33             :                                const unsigned char *param, int plen)
      34             : {
      35           0 :     return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen,
      36             :                                            param, plen, NULL, NULL);
      37             : }
      38             : 
      39           0 : int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
      40             :                                     const unsigned char *from, int flen,
      41             :                                     const unsigned char *param, int plen,
      42             :                                     const EVP_MD *md, const EVP_MD *mgf1md)
      43             : {
      44           0 :     int i, emlen = tlen - 1;
      45             :     unsigned char *db, *seed;
      46             :     unsigned char *dbmask, seedmask[EVP_MAX_MD_SIZE];
      47             :     int mdlen;
      48             : 
      49           0 :     if (md == NULL)
      50           0 :         md = EVP_sha1();
      51           0 :     if (mgf1md == NULL)
      52             :         mgf1md = md;
      53             : 
      54           0 :     mdlen = EVP_MD_size(md);
      55             : 
      56           0 :     if (flen > emlen - 2 * mdlen - 1) {
      57           0 :         RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
      58             :                RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
      59           0 :         return 0;
      60             :     }
      61             : 
      62           0 :     if (emlen < 2 * mdlen + 1) {
      63           0 :         RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
      64             :                RSA_R_KEY_SIZE_TOO_SMALL);
      65           0 :         return 0;
      66             :     }
      67             : 
      68           0 :     to[0] = 0;
      69           0 :     seed = to + 1;
      70           0 :     db = to + mdlen + 1;
      71             : 
      72           0 :     if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
      73             :         return 0;
      74           0 :     memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
      75           0 :     db[emlen - flen - mdlen - 1] = 0x01;
      76           0 :     memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
      77           0 :     if (RAND_bytes(seed, mdlen) <= 0)
      78             :         return 0;
      79             : # ifdef PKCS_TESTVECT
      80             :     memcpy(seed,
      81             :            "\xaa\xfd\x12\xf6\x59\xca\xe6\x34\x89\xb4\x79\xe5\x07\x6d\xde\xc2\xf0\x6c\xb5\x8f",
      82             :            20);
      83             : # endif
      84             : 
      85           0 :     dbmask = OPENSSL_malloc(emlen - mdlen);
      86           0 :     if (dbmask == NULL) {
      87           0 :         RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
      88           0 :         return 0;
      89             :     }
      90             : 
      91           0 :     if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0)
      92             :         return 0;
      93           0 :     for (i = 0; i < emlen - mdlen; i++)
      94           0 :         db[i] ^= dbmask[i];
      95             : 
      96           0 :     if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0)
      97             :         return 0;
      98           0 :     for (i = 0; i < mdlen; i++)
      99           0 :         seed[i] ^= seedmask[i];
     100             : 
     101           0 :     OPENSSL_free(dbmask);
     102           0 :     return 1;
     103             : }
     104             : 
     105           0 : int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
     106             :                                  const unsigned char *from, int flen, int num,
     107             :                                  const unsigned char *param, int plen)
     108             : {
     109           0 :     return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num,
     110             :                                              param, plen, NULL, NULL);
     111             : }
     112             : 
     113           0 : int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
     114             :                                       const unsigned char *from, int flen,
     115             :                                       int num, const unsigned char *param,
     116             :                                       int plen, const EVP_MD *md,
     117             :                                       const EVP_MD *mgf1md)
     118             : {
     119             :     int i, dblen, mlen = -1, one_index = 0, msg_index;
     120             :     unsigned int good, found_one_byte;
     121             :     const unsigned char *maskedseed, *maskeddb;
     122             :     /*
     123             :      * |em| is the encoded message, zero-padded to exactly |num| bytes: em =
     124             :      * Y || maskedSeed || maskedDB
     125             :      */
     126             :     unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE],
     127             :         phash[EVP_MAX_MD_SIZE];
     128             :     int mdlen;
     129             : 
     130           0 :     if (md == NULL)
     131           0 :         md = EVP_sha1();
     132           0 :     if (mgf1md == NULL)
     133             :         mgf1md = md;
     134             : 
     135           0 :     mdlen = EVP_MD_size(md);
     136             : 
     137           0 :     if (tlen <= 0 || flen <= 0)
     138             :         return -1;
     139             :     /*
     140             :      * |num| is the length of the modulus; |flen| is the length of the
     141             :      * encoded message. Therefore, for any |from| that was obtained by
     142             :      * decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
     143             :      * num < 2 * mdlen + 2 must hold for the modulus irrespective of
     144             :      * the ciphertext, see PKCS #1 v2.2, section 7.1.2.
     145             :      * This does not leak any side-channel information.
     146             :      */
     147           0 :     if (num < flen || num < 2 * mdlen + 2)
     148             :         goto decoding_err;
     149             : 
     150           0 :     dblen = num - mdlen - 1;
     151           0 :     db = OPENSSL_malloc(dblen);
     152           0 :     em = OPENSSL_malloc(num);
     153           0 :     if (db == NULL || em == NULL) {
     154           0 :         RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
     155           0 :         goto cleanup;
     156             :     }
     157             : 
     158             :     /*
     159             :      * Always do this zero-padding copy (even when num == flen) to avoid
     160             :      * leaking that information. The copy still leaks some side-channel
     161             :      * information, but it's impossible to have a fixed  memory access
     162             :      * pattern since we can't read out of the bounds of |from|.
     163             :      *
     164             :      * TODO(emilia): Consider porting BN_bn2bin_padded from BoringSSL.
     165             :      */
     166           0 :     memset(em, 0, num);
     167           0 :     memcpy(em + num - flen, from, flen);
     168             : 
     169             :     /*
     170             :      * The first byte must be zero, however we must not leak if this is
     171             :      * true. See James H. Manger, "A Chosen Ciphertext  Attack on RSA
     172             :      * Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
     173             :      */
     174           0 :     good = constant_time_is_zero(em[0]);
     175             : 
     176           0 :     maskedseed = em + 1;
     177           0 :     maskeddb = em + 1 + mdlen;
     178             : 
     179           0 :     if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
     180             :         goto cleanup;
     181           0 :     for (i = 0; i < mdlen; i++)
     182           0 :         seed[i] ^= maskedseed[i];
     183             : 
     184           0 :     if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))
     185             :         goto cleanup;
     186           0 :     for (i = 0; i < dblen; i++)
     187           0 :         db[i] ^= maskeddb[i];
     188             : 
     189           0 :     if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))
     190             :         goto cleanup;
     191             : 
     192           0 :     good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
     193             : 
     194             :     found_one_byte = 0;
     195           0 :     for (i = mdlen; i < dblen; i++) {
     196             :         /*
     197             :          * Padding consists of a number of 0-bytes, followed by a 1.
     198             :          */
     199           0 :         unsigned int equals1 = constant_time_eq(db[i], 1);
     200           0 :         unsigned int equals0 = constant_time_is_zero(db[i]);
     201           0 :         one_index = constant_time_select_int(~found_one_byte & equals1,
     202             :                                              i, one_index);
     203           0 :         found_one_byte |= equals1;
     204           0 :         good &= (found_one_byte | equals0);
     205             :     }
     206             : 
     207           0 :     good &= found_one_byte;
     208             : 
     209             :     /*
     210             :      * At this point |good| is zero unless the plaintext was valid,
     211             :      * so plaintext-awareness ensures timing side-channels are no longer a
     212             :      * concern.
     213             :      */
     214           0 :     if (!good)
     215             :         goto decoding_err;
     216             : 
     217           0 :     msg_index = one_index + 1;
     218           0 :     mlen = dblen - msg_index;
     219             : 
     220           0 :     if (tlen < mlen) {
     221           0 :         RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, RSA_R_DATA_TOO_LARGE);
     222             :         mlen = -1;
     223             :     } else {
     224           0 :         memcpy(to, db + msg_index, mlen);
     225             :         goto cleanup;
     226             :     }
     227             : 
     228             :  decoding_err:
     229             :     /*
     230             :      * To avoid chosen ciphertext attacks, the error message should not
     231             :      * reveal which kind of decoding error happened.
     232             :      */
     233           0 :     RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
     234             :            RSA_R_OAEP_DECODING_ERROR);
     235             :  cleanup:
     236           0 :     if (db != NULL)
     237           0 :         OPENSSL_free(db);
     238           0 :     if (em != NULL)
     239           0 :         OPENSSL_free(em);
     240           0 :     return mlen;
     241             : }
     242             : 
     243           0 : int PKCS1_MGF1(unsigned char *mask, long len,
     244             :                const unsigned char *seed, long seedlen, const EVP_MD *dgst)
     245             : {
     246             :     long i, outlen = 0;
     247             :     unsigned char cnt[4];
     248             :     EVP_MD_CTX c;
     249             :     unsigned char md[EVP_MAX_MD_SIZE];
     250             :     int mdlen;
     251             :     int rv = -1;
     252             : 
     253           0 :     EVP_MD_CTX_init(&c);
     254           0 :     mdlen = EVP_MD_size(dgst);
     255           0 :     if (mdlen < 0)
     256             :         goto err;
     257           0 :     for (i = 0; outlen < len; i++) {
     258           0 :         cnt[0] = (unsigned char)((i >> 24) & 255);
     259           0 :         cnt[1] = (unsigned char)((i >> 16) & 255);
     260           0 :         cnt[2] = (unsigned char)((i >> 8)) & 255;
     261           0 :         cnt[3] = (unsigned char)(i & 255);
     262           0 :         if (!EVP_DigestInit_ex(&c, dgst, NULL)
     263           0 :             || !EVP_DigestUpdate(&c, seed, seedlen)
     264           0 :             || !EVP_DigestUpdate(&c, cnt, 4))
     265             :             goto err;
     266           0 :         if (outlen + mdlen <= len) {
     267           0 :             if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL))
     268             :                 goto err;
     269             :             outlen += mdlen;
     270             :         } else {
     271           0 :             if (!EVP_DigestFinal_ex(&c, md, NULL))
     272             :                 goto err;
     273           0 :             memcpy(mask + outlen, md, len - outlen);
     274             :             outlen = len;
     275             :         }
     276             :     }
     277             :     rv = 0;
     278             :  err:
     279           0 :     EVP_MD_CTX_cleanup(&c);
     280           0 :     return rv;
     281             : }
     282             : 
     283             : #endif

Generated by: LCOV version 1.10