Botan  1.11.15
src/lib/pk_pad/emsa_pssr/pssr.cpp
Go to the documentation of this file.
00001 /*
00002 * PSSR
00003 * (C) 1999-2007 Jack Lloyd
00004 *
00005 * Botan is released under the Simplified BSD License (see license.txt)
00006 */
00007 
00008 #include <botan/internal/pad_utils.h>
00009 #include <botan/pssr.h>
00010 #include <botan/mgf1.h>
00011 #include <botan/internal/bit_ops.h>
00012 
00013 namespace Botan {
00014 
00015 PSSR* PSSR::make(const Spec& request)
00016    {
00017    if(request.arg(1, "MGF1") != "MGF1")
00018       return nullptr;
00019 
00020    auto hash = make_a<HashFunction>(request.arg(0));
00021 
00022    if(!hash)
00023       return nullptr;
00024 
00025    const size_t salt_size = request.arg_as_integer(2, hash->output_length());
00026 
00027    return new PSSR(hash, salt_size);
00028    }
00029 
00030 BOTAN_REGISTER_NAMED_T(EMSA, "PSSR", PSSR, PSSR::make);
00031 
00032 /*
00033 * PSSR Update Operation
00034 */
00035 void PSSR::update(const byte input[], size_t length)
00036    {
00037    hash->update(input, length);
00038    }
00039 
00040 /*
00041 * Return the raw (unencoded) data
00042 */
00043 secure_vector<byte> PSSR::raw_data()
00044    {
00045    return hash->final();
00046    }
00047 
00048 /*
00049 * PSSR Encode Operation
00050 */
00051 secure_vector<byte> PSSR::encoding_of(const secure_vector<byte>& msg,
00052                                       size_t output_bits,
00053                                       RandomNumberGenerator& rng)
00054    {
00055    const size_t HASH_SIZE = hash->output_length();
00056 
00057    if(msg.size() != HASH_SIZE)
00058       throw Encoding_Error("PSSR::encoding_of: Bad input length");
00059    if(output_bits < 8*HASH_SIZE + 8*SALT_SIZE + 9)
00060       throw Encoding_Error("PSSR::encoding_of: Output length is too small");
00061 
00062    const size_t output_length = (output_bits + 7) / 8;
00063 
00064    secure_vector<byte> salt = rng.random_vec(SALT_SIZE);
00065 
00066    for(size_t j = 0; j != 8; ++j)
00067       hash->update(0);
00068    hash->update(msg);
00069    hash->update(salt);
00070    secure_vector<byte> H = hash->final();
00071 
00072    secure_vector<byte> EM(output_length);
00073 
00074    EM[output_length - HASH_SIZE - SALT_SIZE - 2] = 0x01;
00075    buffer_insert(EM, output_length - 1 - HASH_SIZE - SALT_SIZE, salt);
00076    mgf1_mask(*hash, &H[0], HASH_SIZE, &EM[0], output_length - HASH_SIZE - 1);
00077    EM[0] &= 0xFF >> (8 * ((output_bits + 7) / 8) - output_bits);
00078    buffer_insert(EM, output_length - 1 - HASH_SIZE, H);
00079    EM[output_length-1] = 0xBC;
00080 
00081    return EM;
00082    }
00083 
00084 /*
00085 * PSSR Decode/Verify Operation
00086 */
00087 bool PSSR::verify(const secure_vector<byte>& const_coded,
00088                    const secure_vector<byte>& raw, size_t key_bits)
00089    {
00090    const size_t HASH_SIZE = hash->output_length();
00091    const size_t KEY_BYTES = (key_bits + 7) / 8;
00092 
00093    if(key_bits < 8*HASH_SIZE + 9)
00094       return false;
00095 
00096    if(raw.size() != HASH_SIZE)
00097       return false;
00098 
00099    if(const_coded.size() > KEY_BYTES || const_coded.size() <= 1)
00100       return false;
00101 
00102    if(const_coded[const_coded.size()-1] != 0xBC)
00103       return false;
00104 
00105    secure_vector<byte> coded = const_coded;
00106    if(coded.size() < KEY_BYTES)
00107       {
00108       secure_vector<byte> temp(KEY_BYTES);
00109       buffer_insert(temp, KEY_BYTES - coded.size(), coded);
00110       coded = temp;
00111       }
00112 
00113    const size_t TOP_BITS = 8 * ((key_bits + 7) / 8) - key_bits;
00114    if(TOP_BITS > 8 - high_bit(coded[0]))
00115       return false;
00116 
00117    byte* DB = &coded[0];
00118    const size_t DB_size = coded.size() - HASH_SIZE - 1;
00119 
00120    const byte* H = &coded[DB_size];
00121    const size_t H_size = HASH_SIZE;
00122 
00123    mgf1_mask(*hash, &H[0], H_size, &DB[0], DB_size);
00124    DB[0] &= 0xFF >> TOP_BITS;
00125 
00126    size_t salt_offset = 0;
00127    for(size_t j = 0; j != DB_size; ++j)
00128       {
00129       if(DB[j] == 0x01)
00130          { salt_offset = j + 1; break; }
00131       if(DB[j])
00132          return false;
00133       }
00134    if(salt_offset == 0)
00135       return false;
00136 
00137    for(size_t j = 0; j != 8; ++j)
00138       hash->update(0);
00139    hash->update(raw);
00140    hash->update(&DB[salt_offset], DB_size - salt_offset);
00141    secure_vector<byte> H2 = hash->final();
00142 
00143    return same_mem(&H[0], &H2[0], HASH_SIZE);
00144    }
00145 
00146 PSSR::PSSR(HashFunction* h) :
00147    SALT_SIZE(h->output_length()), hash(h)
00148    {
00149    }
00150 
00151 PSSR::PSSR(HashFunction* h, size_t salt_size) :
00152    SALT_SIZE(salt_size), hash(h)
00153    {
00154    }
00155 
00156 }