1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/ssl/libcrypto/src/crypto/rsa/rsa_pss.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,269 @@
1.4 +/* rsa_pss.c */
1.5 +/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
1.6 + * project 2005.
1.7 + */
1.8 +/* ====================================================================
1.9 + * Copyright (c) 2005 The OpenSSL Project. All rights reserved.
1.10 + *
1.11 + * Redistribution and use in source and binary forms, with or without
1.12 + * modification, are permitted provided that the following conditions
1.13 + * are met:
1.14 + *
1.15 + * 1. Redistributions of source code must retain the above copyright
1.16 + * notice, this list of conditions and the following disclaimer.
1.17 + *
1.18 + * 2. Redistributions in binary form must reproduce the above copyright
1.19 + * notice, this list of conditions and the following disclaimer in
1.20 + * the documentation and/or other materials provided with the
1.21 + * distribution.
1.22 + *
1.23 + * 3. All advertising materials mentioning features or use of this
1.24 + * software must display the following acknowledgment:
1.25 + * "This product includes software developed by the OpenSSL Project
1.26 + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
1.27 + *
1.28 + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
1.29 + * endorse or promote products derived from this software without
1.30 + * prior written permission. For written permission, please contact
1.31 + * licensing@OpenSSL.org.
1.32 + *
1.33 + * 5. Products derived from this software may not be called "OpenSSL"
1.34 + * nor may "OpenSSL" appear in their names without prior written
1.35 + * permission of the OpenSSL Project.
1.36 + *
1.37 + * 6. Redistributions of any form whatsoever must retain the following
1.38 + * acknowledgment:
1.39 + * "This product includes software developed by the OpenSSL Project
1.40 + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
1.41 + *
1.42 + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
1.43 + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1.44 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.45 + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
1.46 + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1.47 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1.48 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1.49 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1.50 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
1.51 + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1.52 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
1.53 + * OF THE POSSIBILITY OF SUCH DAMAGE.
1.54 + * ====================================================================
1.55 + *
1.56 + * This product includes cryptographic software written by Eric Young
1.57 + * (eay@cryptsoft.com). This product includes software written by Tim
1.58 + * Hudson (tjh@cryptsoft.com).
1.59 + *
1.60 + */
1.61 +
1.62 +#include <stdio.h>
1.63 +#include "cryptlib.h"
1.64 +#include <openssl/bn.h>
1.65 +#include <openssl/rsa.h>
1.66 +#include <openssl/evp.h>
1.67 +#include <openssl/rand.h>
1.68 +#include <openssl/sha.h>
1.69 +
1.70 +static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
1.71 +
1.72 +#if defined(_MSC_VER) && defined(_ARM_)
1.73 +#pragma optimize("g", off)
1.74 +#endif
1.75 +
1.76 +EXPORT_C int RSA_verify_PKCS1_PSS(RSA *rsa, const unsigned char *mHash,
1.77 + const EVP_MD *Hash, const unsigned char *EM, int sLen)
1.78 + {
1.79 + int i;
1.80 + int ret = 0;
1.81 + int hLen, maskedDBLen, MSBits, emLen;
1.82 + const unsigned char *H;
1.83 + unsigned char *DB = NULL;
1.84 + EVP_MD_CTX ctx;
1.85 + unsigned char H_[EVP_MAX_MD_SIZE];
1.86 +
1.87 + hLen = EVP_MD_size(Hash);
1.88 + /*
1.89 + * Negative sLen has special meanings:
1.90 + * -1 sLen == hLen
1.91 + * -2 salt length is autorecovered from signature
1.92 + * -N reserved
1.93 + */
1.94 + if (sLen == -1) sLen = hLen;
1.95 + else if (sLen == -2) sLen = -2;
1.96 + else if (sLen < -2)
1.97 + {
1.98 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
1.99 + goto err;
1.100 + }
1.101 +
1.102 + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
1.103 + emLen = RSA_size(rsa);
1.104 + if (EM[0] & (0xFF << MSBits))
1.105 + {
1.106 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_FIRST_OCTET_INVALID);
1.107 + goto err;
1.108 + }
1.109 + if (MSBits == 0)
1.110 + {
1.111 + EM++;
1.112 + emLen--;
1.113 + }
1.114 + if (emLen < (hLen + sLen + 2)) /* sLen can be small negative */
1.115 + {
1.116 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_DATA_TOO_LARGE);
1.117 + goto err;
1.118 + }
1.119 + if (EM[emLen - 1] != 0xbc)
1.120 + {
1.121 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_LAST_OCTET_INVALID);
1.122 + goto err;
1.123 + }
1.124 + maskedDBLen = emLen - hLen - 1;
1.125 + H = EM + maskedDBLen;
1.126 + DB = OPENSSL_malloc(maskedDBLen);
1.127 + if (!DB)
1.128 + {
1.129 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, ERR_R_MALLOC_FAILURE);
1.130 + goto err;
1.131 + }
1.132 + PKCS1_MGF1(DB, maskedDBLen, H, hLen, Hash);
1.133 + for (i = 0; i < maskedDBLen; i++)
1.134 + DB[i] ^= EM[i];
1.135 + if (MSBits)
1.136 + DB[0] &= 0xFF >> (8 - MSBits);
1.137 + for (i = 0; DB[i] == 0 && i < (maskedDBLen-1); i++) ;
1.138 + if (DB[i++] != 0x1)
1.139 + {
1.140 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_RECOVERY_FAILED);
1.141 + goto err;
1.142 + }
1.143 + if (sLen >= 0 && (maskedDBLen - i) != sLen)
1.144 + {
1.145 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
1.146 + goto err;
1.147 + }
1.148 + EVP_MD_CTX_init(&ctx);
1.149 + EVP_DigestInit_ex(&ctx, Hash, NULL);
1.150 + EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
1.151 + EVP_DigestUpdate(&ctx, mHash, hLen);
1.152 + if (maskedDBLen - i)
1.153 + EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i);
1.154 + EVP_DigestFinal(&ctx, H_, NULL);
1.155 + EVP_MD_CTX_cleanup(&ctx);
1.156 + if (memcmp(H_, H, hLen))
1.157 + {
1.158 + RSAerr(RSA_F_RSA_VERIFY_PKCS1_PSS, RSA_R_BAD_SIGNATURE);
1.159 + ret = 0;
1.160 + }
1.161 + else
1.162 + ret = 1;
1.163 +
1.164 + err:
1.165 + if (DB)
1.166 + OPENSSL_free(DB);
1.167 +
1.168 + return ret;
1.169 +
1.170 + }
1.171 +
1.172 +EXPORT_C int RSA_padding_add_PKCS1_PSS(RSA *rsa, unsigned char *EM,
1.173 + const unsigned char *mHash,
1.174 + const EVP_MD *Hash, int sLen)
1.175 + {
1.176 + int i;
1.177 + int ret = 0;
1.178 + int hLen, maskedDBLen, MSBits, emLen;
1.179 + unsigned char *H, *salt = NULL, *p;
1.180 + EVP_MD_CTX ctx;
1.181 +
1.182 + hLen = EVP_MD_size(Hash);
1.183 + /*
1.184 + * Negative sLen has special meanings:
1.185 + * -1 sLen == hLen
1.186 + * -2 salt length is maximized
1.187 + * -N reserved
1.188 + */
1.189 + if (sLen == -1) sLen = hLen;
1.190 + else if (sLen == -2) sLen = -2;
1.191 + else if (sLen < -2)
1.192 + {
1.193 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS, RSA_R_SLEN_CHECK_FAILED);
1.194 + goto err;
1.195 + }
1.196 +
1.197 + MSBits = (BN_num_bits(rsa->n) - 1) & 0x7;
1.198 + emLen = RSA_size(rsa);
1.199 + if (MSBits == 0)
1.200 + {
1.201 + *EM++ = 0;
1.202 + emLen--;
1.203 + }
1.204 + if (sLen == -2)
1.205 + {
1.206 + sLen = emLen - hLen - 2;
1.207 + }
1.208 + else if (emLen < (hLen + sLen + 2))
1.209 + {
1.210 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
1.211 + RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
1.212 + goto err;
1.213 + }
1.214 + if (sLen > 0)
1.215 + {
1.216 + salt = OPENSSL_malloc(sLen);
1.217 + if (!salt)
1.218 + {
1.219 + RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_PSS,
1.220 + ERR_R_MALLOC_FAILURE);
1.221 + goto err;
1.222 + }
1.223 + if (!RAND_bytes(salt, sLen))
1.224 + goto err;
1.225 + }
1.226 + maskedDBLen = emLen - hLen - 1;
1.227 + H = EM + maskedDBLen;
1.228 + EVP_MD_CTX_init(&ctx);
1.229 + EVP_DigestInit_ex(&ctx, Hash, NULL);
1.230 + EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes);
1.231 + EVP_DigestUpdate(&ctx, mHash, hLen);
1.232 + if (sLen)
1.233 + EVP_DigestUpdate(&ctx, salt, sLen);
1.234 + EVP_DigestFinal(&ctx, H, NULL);
1.235 + EVP_MD_CTX_cleanup(&ctx);
1.236 +
1.237 + /* Generate dbMask in place then perform XOR on it */
1.238 + PKCS1_MGF1(EM, maskedDBLen, H, hLen, Hash);
1.239 +
1.240 + p = EM;
1.241 +
1.242 + /* Initial PS XORs with all zeroes which is a NOP so just update
1.243 + * pointer. Note from a test above this value is guaranteed to
1.244 + * be non-negative.
1.245 + */
1.246 + p += emLen - sLen - hLen - 2;
1.247 + *p++ ^= 0x1;
1.248 + if (sLen > 0)
1.249 + {
1.250 + for (i = 0; i < sLen; i++)
1.251 + *p++ ^= salt[i];
1.252 + }
1.253 + if (MSBits)
1.254 + EM[0] &= 0xFF >> (8 - MSBits);
1.255 +
1.256 + /* H is already in place so just set final 0xbc */
1.257 +
1.258 + EM[emLen - 1] = 0xbc;
1.259 +
1.260 + ret = 1;
1.261 +
1.262 + err:
1.263 + if (salt)
1.264 + OPENSSL_free(salt);
1.265 +
1.266 + return ret;
1.267 +
1.268 + }
1.269 +
1.270 +#if defined(_MSC_VER)
1.271 +#pragma optimize("",on)
1.272 +#endif