diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/rsa/rsa_sign.c | 268 |
1 files changed, 148 insertions, 120 deletions
diff --git a/src/lib/libcrypto/rsa/rsa_sign.c b/src/lib/libcrypto/rsa/rsa_sign.c index 6e9e869f0a..2383259dda 100644 --- a/src/lib/libcrypto/rsa/rsa_sign.c +++ b/src/lib/libcrypto/rsa/rsa_sign.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: rsa_sign.c,v 1.29 2017/05/02 03:59:45 deraadt Exp $ */ | 1 | /* $OpenBSD: rsa_sign.c,v 1.30 2018/07/23 17:37:17 tb Exp $ */ |
| 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
| 3 | * All rights reserved. | 3 | * All rights reserved. |
| 4 | * | 4 | * |
| @@ -70,168 +70,196 @@ | |||
| 70 | /* Size of an SSL signature: MD5+SHA1 */ | 70 | /* Size of an SSL signature: MD5+SHA1 */ |
| 71 | #define SSL_SIG_LENGTH 36 | 71 | #define SSL_SIG_LENGTH 36 |
| 72 | 72 | ||
| 73 | int | 73 | static int encode_pkcs1(unsigned char **, int *, int , const unsigned char *, |
| 74 | RSA_sign(int type, const unsigned char *m, unsigned int m_len, | 74 | unsigned int); |
| 75 | unsigned char *sigret, unsigned int *siglen, RSA *rsa) | 75 | |
| 76 | /* | ||
| 77 | * encode_pkcs1 encodes a DigestInfo prefix of hash `type' and digest `m', as | ||
| 78 | * described in EMSA-PKCS-v1_5-ENCODE, RFC 8017 section 9. step 2. This | ||
| 79 | * encodes the DigestInfo (T and tLen) but does not add the padding. | ||
| 80 | * | ||
| 81 | * On success, it returns one and sets `*out' to a newly allocated buffer | ||
| 82 | * containing the result and `*out_len' to its length. Freeing `*out' is | ||
| 83 | * the caller's responsibility. Failure is indicated by zero. | ||
| 84 | */ | ||
| 85 | static int | ||
| 86 | encode_pkcs1(unsigned char **out, int *out_len, int type, | ||
| 87 | const unsigned char *m, unsigned int m_len) | ||
| 76 | { | 88 | { |
| 77 | X509_SIG sig; | 89 | X509_SIG sig; |
| 78 | ASN1_TYPE parameter; | ||
| 79 | int i, j, ret = 1; | ||
| 80 | unsigned char *p, *tmps = NULL; | ||
| 81 | const unsigned char *s = NULL; | ||
| 82 | X509_ALGOR algor; | 90 | X509_ALGOR algor; |
| 91 | ASN1_TYPE parameter; | ||
| 83 | ASN1_OCTET_STRING digest; | 92 | ASN1_OCTET_STRING digest; |
| 93 | uint8_t *der = NULL; | ||
| 94 | int len; | ||
| 95 | |||
| 96 | sig.algor = &algor; | ||
| 97 | if ((sig.algor->algorithm = OBJ_nid2obj(type)) == NULL) { | ||
| 98 | RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE); | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | if (sig.algor->algorithm->length == 0) { | ||
| 102 | RSAerror( | ||
| 103 | RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); | ||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | parameter.type = V_ASN1_NULL; | ||
| 107 | parameter.value.ptr = NULL; | ||
| 108 | sig.algor->parameter = ¶meter; | ||
| 109 | |||
| 110 | sig.digest = &digest; | ||
| 111 | sig.digest->data = (unsigned char*)m; /* TMP UGLY CAST */ | ||
| 112 | sig.digest->length = m_len; | ||
| 84 | 113 | ||
| 85 | if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign) | 114 | if ((len = i2d_X509_SIG(&sig, &der)) < 0) |
| 115 | return 0; | ||
| 116 | |||
| 117 | *out = der; | ||
| 118 | *out_len = len; | ||
| 119 | |||
| 120 | return 1; | ||
| 121 | } | ||
| 122 | |||
| 123 | int | ||
| 124 | RSA_sign(int type, const unsigned char *m, unsigned int m_len, | ||
| 125 | unsigned char *sigret, unsigned int *siglen, RSA *rsa) | ||
| 126 | { | ||
| 127 | const unsigned char *encoded = NULL; | ||
| 128 | unsigned char *tmps = NULL; | ||
| 129 | int encrypt_len, encoded_len = 0, ret = 0; | ||
| 130 | |||
| 131 | if ((rsa->flags & RSA_FLAG_SIGN_VER) && rsa->meth->rsa_sign != NULL) | ||
| 86 | return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); | 132 | return rsa->meth->rsa_sign(type, m, m_len, sigret, siglen, rsa); |
| 87 | 133 | ||
| 88 | /* Special case: SSL signature, just check the length */ | 134 | /* Compute the encoded digest. */ |
| 89 | if (type == NID_md5_sha1) { | 135 | if (type == NID_md5_sha1) { |
| 136 | /* | ||
| 137 | * NID_md5_sha1 corresponds to the MD5/SHA1 combination in | ||
| 138 | * TLS 1.1 and earlier. It has no DigestInfo wrapper but | ||
| 139 | * otherwise is RSASSA-PKCS-v1.5. | ||
| 140 | */ | ||
| 90 | if (m_len != SSL_SIG_LENGTH) { | 141 | if (m_len != SSL_SIG_LENGTH) { |
| 91 | RSAerror(RSA_R_INVALID_MESSAGE_LENGTH); | 142 | RSAerror(RSA_R_INVALID_DIGEST_LENGTH); |
| 92 | return 0; | 143 | return 0; |
| 93 | } | 144 | } |
| 94 | i = SSL_SIG_LENGTH; | 145 | encoded_len = SSL_SIG_LENGTH; |
| 95 | s = m; | 146 | encoded = m; |
| 96 | } else { | 147 | } else { |
| 97 | sig.algor = &algor; | 148 | if (!encode_pkcs1(&tmps, &encoded_len, type, m, m_len)) |
| 98 | sig.algor->algorithm = OBJ_nid2obj(type); | 149 | goto err; |
| 99 | if (sig.algor->algorithm == NULL) { | 150 | encoded = tmps; |
| 100 | RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE); | ||
| 101 | return 0; | ||
| 102 | } | ||
| 103 | if (sig.algor->algorithm->length == 0) { | ||
| 104 | RSAerror(RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | parameter.type = V_ASN1_NULL; | ||
| 108 | parameter.value.ptr = NULL; | ||
| 109 | sig.algor->parameter = ¶meter; | ||
| 110 | |||
| 111 | sig.digest = &digest; | ||
| 112 | sig.digest->data = (unsigned char *)m; /* TMP UGLY CAST */ | ||
| 113 | sig.digest->length = m_len; | ||
| 114 | |||
| 115 | i = i2d_X509_SIG(&sig, NULL); | ||
| 116 | } | 151 | } |
| 117 | j = RSA_size(rsa); | 152 | if (encoded_len > RSA_size(rsa) - RSA_PKCS1_PADDING_SIZE) { |
| 118 | if (i > j - RSA_PKCS1_PADDING_SIZE) { | ||
| 119 | RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); | 153 | RSAerror(RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY); |
| 120 | return 0; | 154 | goto err; |
| 121 | } | ||
| 122 | if (type != NID_md5_sha1) { | ||
| 123 | tmps = malloc(j + 1); | ||
| 124 | if (tmps == NULL) { | ||
| 125 | RSAerror(ERR_R_MALLOC_FAILURE); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | p = tmps; | ||
| 129 | i2d_X509_SIG(&sig, &p); | ||
| 130 | s = tmps; | ||
| 131 | } | 155 | } |
| 132 | i = RSA_private_encrypt(i, s, sigret, rsa, RSA_PKCS1_PADDING); | 156 | if ((encrypt_len = RSA_private_encrypt(encoded_len, encoded, sigret, |
| 133 | if (i <= 0) | 157 | rsa, RSA_PKCS1_PADDING)) <= 0) |
| 134 | ret = 0; | 158 | goto err; |
| 135 | else | 159 | |
| 136 | *siglen = i; | 160 | *siglen = encrypt_len; |
| 137 | 161 | ret = 1; | |
| 138 | if (type != NID_md5_sha1) | 162 | |
| 139 | freezero(tmps, (unsigned int)j + 1); | 163 | err: |
| 164 | freezero(tmps, (size_t)encoded_len); | ||
| 140 | return (ret); | 165 | return (ret); |
| 141 | } | 166 | } |
| 142 | 167 | ||
| 168 | /* | ||
| 169 | * int_rsa_verify verifies an RSA signature in `sigbuf' using `rsa'. It may be | ||
| 170 | * called in two modes. If `rm' is NULL, it verifies the signature for the | ||
| 171 | * digest `m'. Otherwise, it recovers the digest from the signature, writing the | ||
| 172 | * digest to `rm' and the length to `*prm_len'. `type' is the NID of the digest | ||
| 173 | * algorithm to use. It returns one on successful verification and zero | ||
| 174 | * otherwise. | ||
| 175 | */ | ||
| 143 | int | 176 | int |
| 144 | int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len, | 177 | int_rsa_verify(int type, const unsigned char *m, unsigned int m_len, |
| 145 | unsigned char *rm, size_t *prm_len, const unsigned char *sigbuf, | 178 | unsigned char *rm, size_t *prm_len, const unsigned char *sigbuf, |
| 146 | size_t siglen, RSA *rsa) | 179 | size_t siglen, RSA *rsa) |
| 147 | { | 180 | { |
| 148 | int i, ret = 0, sigtype; | 181 | unsigned char *decrypt_buf, *encoded = NULL; |
| 149 | unsigned char *s; | 182 | int decrypt_len, encoded_len = 0, ret = 0; |
| 150 | X509_SIG *sig = NULL; | ||
| 151 | 183 | ||
| 152 | if (siglen != (unsigned int)RSA_size(rsa)) { | 184 | if (siglen != (size_t)RSA_size(rsa)) { |
| 153 | RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH); | 185 | RSAerror(RSA_R_WRONG_SIGNATURE_LENGTH); |
| 154 | return 0; | 186 | return 0; |
| 155 | } | 187 | } |
| 156 | 188 | ||
| 157 | if ((dtype == NID_md5_sha1) && rm) { | 189 | /* Recover the encoded digest. */ |
| 158 | i = RSA_public_decrypt((int)siglen, sigbuf, rm, rsa, | 190 | if ((decrypt_buf = malloc(siglen)) == NULL) { |
| 159 | RSA_PKCS1_PADDING); | ||
| 160 | if (i <= 0) | ||
| 161 | return 0; | ||
| 162 | *prm_len = i; | ||
| 163 | return 1; | ||
| 164 | } | ||
| 165 | |||
| 166 | s = malloc(siglen); | ||
| 167 | if (s == NULL) { | ||
| 168 | RSAerror(ERR_R_MALLOC_FAILURE); | 191 | RSAerror(ERR_R_MALLOC_FAILURE); |
| 169 | goto err; | 192 | goto err; |
| 170 | } | 193 | } |
| 171 | if (dtype == NID_md5_sha1 && m_len != SSL_SIG_LENGTH) { | 194 | if ((decrypt_len = RSA_public_decrypt((int)siglen, sigbuf, decrypt_buf, |
| 172 | RSAerror(RSA_R_INVALID_MESSAGE_LENGTH); | 195 | rsa, RSA_PKCS1_PADDING)) <= 0) |
| 173 | goto err; | ||
| 174 | } | ||
| 175 | i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING); | ||
| 176 | |||
| 177 | if (i <= 0) | ||
| 178 | goto err; | 196 | goto err; |
| 197 | |||
| 198 | if (type == NID_md5_sha1) { | ||
| 199 | /* | ||
| 200 | * NID_md5_sha1 corresponds to the MD5/SHA1 combination in | ||
| 201 | * TLS 1.1 and earlier. It has no DigestInfo wrapper but | ||
| 202 | * otherwise is RSASSA-PKCS1-v1_5. | ||
| 203 | */ | ||
| 204 | if (decrypt_len != SSL_SIG_LENGTH) { | ||
| 205 | RSAerror(RSA_R_INVALID_DIGEST_LENGTH); | ||
| 206 | goto err; | ||
| 207 | } | ||
| 179 | 208 | ||
| 180 | /* Special case: SSL signature */ | 209 | if (rm != NULL) { |
| 181 | if (dtype == NID_md5_sha1) { | 210 | memcpy(rm, decrypt_buf, SSL_SIG_LENGTH); |
| 182 | if (i != SSL_SIG_LENGTH || memcmp(s, m, SSL_SIG_LENGTH)) | 211 | *prm_len = SSL_SIG_LENGTH; |
| 183 | RSAerror(RSA_R_BAD_SIGNATURE); | 212 | } else { |
| 184 | else | 213 | if (m_len != SSL_SIG_LENGTH) { |
| 185 | ret = 1; | 214 | RSAerror(RSA_R_INVALID_MESSAGE_LENGTH); |
| 215 | goto err; | ||
| 216 | } | ||
| 217 | if (memcmp(decrypt_buf, m, SSL_SIG_LENGTH) != 0) { | ||
| 218 | RSAerror(RSA_R_BAD_SIGNATURE); | ||
| 219 | goto err; | ||
| 220 | } | ||
| 221 | } | ||
| 186 | } else { | 222 | } else { |
| 187 | const unsigned char *p = s; | 223 | /* |
| 224 | * If recovering the digest, extract a digest-sized output from | ||
| 225 | * the end of `decrypt_buf' for `encode_pkcs1', then compare the | ||
| 226 | * decryption output as in a standard verification. | ||
| 227 | */ | ||
| 228 | if (rm != NULL) { | ||
| 229 | const EVP_MD *md; | ||
| 188 | 230 | ||
| 189 | sig = d2i_X509_SIG(NULL, &p, (long)i); | 231 | if ((md = EVP_get_digestbynid(type)) == NULL) { |
| 232 | RSAerror(RSA_R_UNKNOWN_ALGORITHM_TYPE); | ||
| 233 | goto err; | ||
| 234 | } | ||
| 235 | if ((m_len = EVP_MD_size(md)) > (size_t)decrypt_len) { | ||
| 236 | RSAerror(RSA_R_INVALID_DIGEST_LENGTH); | ||
| 237 | goto err; | ||
| 238 | } | ||
| 239 | m = decrypt_buf + decrypt_len - m_len; | ||
| 240 | } | ||
| 190 | 241 | ||
| 191 | if (sig == NULL) | 242 | /* Construct the encoded digest and ensure it matches */ |
| 243 | if (!encode_pkcs1(&encoded, &encoded_len, type, m, m_len)) | ||
| 192 | goto err; | 244 | goto err; |
| 193 | 245 | ||
| 194 | /* Excess data can be used to create forgeries */ | 246 | if (encoded_len != decrypt_len || |
| 195 | if (p != s + i) { | 247 | memcmp(encoded, decrypt_buf, encoded_len) != 0) { |
| 196 | RSAerror(RSA_R_BAD_SIGNATURE); | 248 | RSAerror(RSA_R_BAD_SIGNATURE); |
| 197 | goto err; | 249 | goto err; |
| 198 | } | 250 | } |
| 199 | 251 | ||
| 200 | /* Parameters to the signature algorithm can also be used to | 252 | /* Output the recovered digest. */ |
| 201 | create forgeries */ | 253 | if (rm != NULL) { |
| 202 | if (sig->algor->parameter && | 254 | memcpy(rm, m, m_len); |
| 203 | ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) { | 255 | *prm_len = m_len; |
| 204 | RSAerror(RSA_R_BAD_SIGNATURE); | ||
| 205 | goto err; | ||
| 206 | } | 256 | } |
| 207 | |||
| 208 | sigtype = OBJ_obj2nid(sig->algor->algorithm); | ||
| 209 | |||
| 210 | if (sigtype != dtype) { | ||
| 211 | RSAerror(RSA_R_ALGORITHM_MISMATCH); | ||
| 212 | goto err; | ||
| 213 | } | ||
| 214 | if (rm) { | ||
| 215 | const EVP_MD *md; | ||
| 216 | |||
| 217 | md = EVP_get_digestbynid(dtype); | ||
| 218 | if (md && (EVP_MD_size(md) != sig->digest->length)) | ||
| 219 | RSAerror(RSA_R_INVALID_DIGEST_LENGTH); | ||
| 220 | else { | ||
| 221 | memcpy(rm, sig->digest->data, | ||
| 222 | sig->digest->length); | ||
| 223 | *prm_len = sig->digest->length; | ||
| 224 | ret = 1; | ||
| 225 | } | ||
| 226 | } else if ((unsigned int)sig->digest->length != m_len || | ||
| 227 | memcmp(m, sig->digest->data, m_len) != 0) { | ||
| 228 | RSAerror(RSA_R_BAD_SIGNATURE); | ||
| 229 | } else | ||
| 230 | ret = 1; | ||
| 231 | } | 257 | } |
| 232 | err: | 258 | |
| 233 | X509_SIG_free(sig); | 259 | ret = 1; |
| 234 | freezero(s, (unsigned int)siglen); | 260 | err: |
| 261 | freezero(encoded, (size_t)encoded_len); | ||
| 262 | freezero(decrypt_buf, siglen); | ||
| 235 | return ret; | 263 | return ret; |
| 236 | } | 264 | } |
| 237 | 265 | ||
