aboutsummaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys/verify_pefile.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asymmetric_keys/verify_pefile.c')
-rw-r--r--crypto/asymmetric_keys/verify_pefile.c49
1 files changed, 33 insertions, 16 deletions
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c
index 79175e6ea0b2..2421f46184ce 100644
--- a/crypto/asymmetric_keys/verify_pefile.c
+++ b/crypto/asymmetric_keys/verify_pefile.c
@@ -128,6 +128,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
128{ 128{
129 struct win_certificate wrapper; 129 struct win_certificate wrapper;
130 const u8 *pkcs7; 130 const u8 *pkcs7;
131 unsigned len;
131 132
132 if (ctx->sig_len < sizeof(wrapper)) { 133 if (ctx->sig_len < sizeof(wrapper)) {
133 pr_debug("Signature wrapper too short\n"); 134 pr_debug("Signature wrapper too short\n");
@@ -154,33 +155,49 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
154 return -ENOTSUPP; 155 return -ENOTSUPP;
155 } 156 }
156 157
157 /* Looks like actual pkcs signature length is in wrapper->length. 158 /* It looks like the pkcs signature length in wrapper->length and the
158 * size obtained from data dir entries lists the total size of 159 * size obtained from the data dir entries, which lists the total size
159 * certificate table which is also aligned to octawrod boundary. 160 * of certificate table, are both aligned to an octaword boundary, so
160 * 161 * we may have to deal with some padding.
161 * So set signature length field appropriately.
162 */ 162 */
163 ctx->sig_len = wrapper.length; 163 ctx->sig_len = wrapper.length;
164 ctx->sig_offset += sizeof(wrapper); 164 ctx->sig_offset += sizeof(wrapper);
165 ctx->sig_len -= sizeof(wrapper); 165 ctx->sig_len -= sizeof(wrapper);
166 if (ctx->sig_len == 0) { 166 if (ctx->sig_len < 4) {
167 pr_debug("Signature data missing\n"); 167 pr_debug("Signature data missing\n");
168 return -EKEYREJECTED; 168 return -EKEYREJECTED;
169 } 169 }
170 170
171 /* What's left should a PKCS#7 cert */ 171 /* What's left should be a PKCS#7 cert */
172 pkcs7 = pebuf + ctx->sig_offset; 172 pkcs7 = pebuf + ctx->sig_offset;
173 if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) { 173 if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
174 if (pkcs7[1] == 0x82 && 174 goto not_pkcs7;
175 pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) && 175
176 pkcs7[3] == ((ctx->sig_len - 4) & 0xff)) 176 switch (pkcs7[1]) {
177 return 0; 177 case 0 ... 0x7f:
178 if (pkcs7[1] == 0x80) 178 len = pkcs7[1] + 2;
179 return 0; 179 goto check_len;
180 if (pkcs7[1] > 0x82) 180 case ASN1_INDEFINITE_LENGTH:
181 return -EMSGSIZE; 181 return 0;
182 case 0x81:
183 len = pkcs7[2] + 3;
184 goto check_len;
185 case 0x82:
186 len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
187 goto check_len;
188 case 0x83 ... 0xff:
189 return -EMSGSIZE;
190 default:
191 goto not_pkcs7;
182 } 192 }
183 193
194check_len:
195 if (len <= ctx->sig_len) {
196 /* There may be padding */
197 ctx->sig_len = len;
198 return 0;
199 }
200not_pkcs7:
184 pr_debug("Signature data not PKCS#7\n"); 201 pr_debug("Signature data not PKCS#7\n");
185 return -ELIBBAD; 202 return -ELIBBAD;
186} 203}