Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/android/webapk/libs/client/src/org/chromium/webapk/lib/client/WebApkVerifySignature.java

Issue 2896273005: Fix bug in one conditional. Add more apk test files. (Closed)
Patch Set: Check for gaps between files in zip. Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/android/webapk/libs/client/junit/src/org/chromium/webapk/lib/client/WebApkValidatorTest.java ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 package org.chromium.webapk.lib.client; 5 package org.chromium.webapk.lib.client;
6 6
7 import static java.nio.ByteOrder.LITTLE_ENDIAN; 7 import static java.nio.ByteOrder.LITTLE_ENDIAN;
8 8
9 import android.support.annotation.IntDef; 9 import android.support.annotation.IntDef;
10 import android.util.Log; 10 import android.util.Log;
11 11
12 import java.nio.ByteBuffer; 12 import java.nio.ByteBuffer;
13 import java.security.PublicKey; 13 import java.security.PublicKey;
14 import java.security.Signature; 14 import java.security.Signature;
15 import java.util.ArrayList; 15 import java.util.ArrayList;
16 import java.util.Collections; 16 import java.util.Collections;
17 import java.util.Comparator;
17 import java.util.regex.Matcher; 18 import java.util.regex.Matcher;
18 import java.util.regex.Pattern; 19 import java.util.regex.Pattern;
19 20
20 /** 21 /**
21 * WebApkVerifySignature reads in the APK file and verifies the WebApk signature . It reads the 22 * WebApkVerifySignature reads in the APK file and verifies the WebApk signature . It reads the
22 * signature from the zip comment and verifies that it was signed by the public key passed. 23 * signature from the zip comment and verifies that it was signed by the public key passed.
23 */ 24 */
24 public class WebApkVerifySignature { 25 public class WebApkVerifySignature {
25 /** Errors codes. */ 26 /** Errors codes. */
26 @IntDef({ 27 @IntDef({
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 mHeaderSize = 0; 120 mHeaderSize = 0;
120 mCompressedSize = compressedSize; 121 mCompressedSize = compressedSize;
121 } 122 }
122 123
123 /** Added for Comparable, sort lexicographically. */ 124 /** Added for Comparable, sort lexicographically. */
124 @Override 125 @Override
125 public int compareTo(Block o) { 126 public int compareTo(Block o) {
126 return mFilename.compareTo(o.mFilename); 127 return mFilename.compareTo(o.mFilename);
127 } 128 }
128 129
130 /** Comparator for sorting the list by position ascending. */
131 public static Comparator<Block> positionComparator = new Comparator<Bloc k>() {
132 @Override
133 public int compare(Block b1, Block b2) {
134 return b1.mPosition - b2.mPosition;
135 }
136 };
137
129 @Override 138 @Override
130 public boolean equals(Object o) { 139 public boolean equals(Object o) {
131 if (!(o instanceof Block)) return false; 140 if (!(o instanceof Block)) return false;
132 return mFilename.equals(((Block) o).mFilename); 141 return mFilename.equals(((Block) o).mFilename);
133 } 142 }
134 143
135 @Override 144 @Override
136 public int hashCode() { 145 public int hashCode() {
137 return mFilename.hashCode(); 146 return mFilename.hashCode();
138 } 147 }
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 return ERROR_COMMENT_TOO_LARGE; 326 return ERROR_COMMENT_TOO_LARGE;
318 } 327 }
319 mBlocks.add(new Block(filename, offset, compressedSize)); 328 mBlocks.add(new Block(filename, offset, compressedSize));
320 } 329 }
321 330
322 if (mBuffer.position() != mEndOfCentralDirOffset) { 331 if (mBuffer.position() != mEndOfCentralDirOffset) {
323 // At this point we should be exactly at the EOCD start. 332 // At this point we should be exactly at the EOCD start.
324 return ERROR_BAD_BLANK_SPACE; 333 return ERROR_BAD_BLANK_SPACE;
325 } 334 }
326 335
327 boolean hasBlockAtStart = false; 336 // We need blocks to be sorted by position at this point.
328 long positionOfLastByteOfLastBlock = 0; 337 Collections.sort(mBlocks, Block.positionComparator);
338 int lastByte = 0;
329 339
330 // Read the 'local file header' block to the size of the header in bytes . 340 // Read the 'local file header' block to the size of the header in bytes .
331 for (Block block : mBlocks) { 341 for (Block block : mBlocks) {
342 if (block.mPosition != lastByte) {
343 return ERROR_BAD_BLANK_SPACE;
344 }
345
332 seek(block.mPosition); 346 seek(block.mPosition);
333 if (block.mPosition == 0) {
334 hasBlockAtStart = true;
335 }
336 int signature = read4(); 347 int signature = read4();
337 if (signature != LFH_SIG) { 348 if (signature != LFH_SIG) {
338 Log.d(TAG, "LFH Signature missing"); 349 Log.d(TAG, "LFH Signature missing");
339 return ERROR_BAD_APK; 350 return ERROR_BAD_APK;
340 } 351 }
341 // ReaderVersion(2) 352 // ReaderVersion(2)
342 seekDelta(2); 353 seekDelta(2);
343 int flags = read2(); 354 int flags = read2();
344 // CompressionMethod(2), ModifiedTime (2), ModifiedDate(2), CRC32(4) , CompressedSize(4), 355 // CompressionMethod(2), ModifiedTime (2), ModifiedDate(2), CRC32(4) , CompressedSize(4),
345 // UncompressedSize(4) = 18 bytes 356 // UncompressedSize(4) = 18 bytes
346 seekDelta(18); 357 seekDelta(18);
347 int fileNameLength = read2(); 358 int fileNameLength = read2();
348 int extraFieldLength = read2(); 359 int extraFieldLength = read2();
349 if (extraFieldLength > MAX_EXTRA_LENGTH) { 360 if (extraFieldLength > MAX_EXTRA_LENGTH) {
350 return ERROR_EXTRA_FIELD_TOO_LARGE; 361 return ERROR_EXTRA_FIELD_TOO_LARGE;
351 } 362 }
352 363
353 block.mHeaderSize = 364 block.mHeaderSize =
354 (mBuffer.position() - block.mPosition) + fileNameLength + ex traFieldLength; 365 (mBuffer.position() - block.mPosition) + fileNameLength + ex traFieldLength;
355 366
356 int lastByte = block.mPosition + block.mHeaderSize + block.mCompress edSize; 367 lastByte = block.mPosition + block.mHeaderSize + block.mCompressedSi ze;
357 if ((flags & 0x8) != 0) { 368 if ((flags & 0x8) != 0) {
358 seek(lastByte); 369 seek(lastByte);
359 if (read4() == DATA_DESCRIPTOR_SIG) { 370 if (read4() == DATA_DESCRIPTOR_SIG) {
360 // Data descriptor, style 1: sig(4), crc-32(4), compressed s ize(4), 371 // Data descriptor, style 1: sig(4), crc-32(4), compressed s ize(4),
361 // uncompressed size(4) = 16 bytes 372 // uncompressed size(4) = 16 bytes
362 lastByte += 16; 373 lastByte += 16;
363 } else { 374 } else {
364 // Data descriptor, style 2: crc-32(4), compressed size(4), 375 // Data descriptor, style 2: crc-32(4), compressed size(4),
365 // uncompressed size(4) = 12 bytes 376 // uncompressed size(4) = 12 bytes
366 lastByte += 12; 377 lastByte += 12;
367 } 378 }
368 } 379 }
369 if (lastByte > positionOfLastByteOfLastBlock) {
370 positionOfLastByteOfLastBlock = lastByte;
371 }
372 } 380 }
373 if (!hasBlockAtStart) { 381 if (lastByte != mCentralDirOffset) {
374 return ERROR_BAD_BLANK_SPACE;
375 }
376 if (positionOfLastByteOfLastBlock != mCentralDirOffset) {
377 seek(mCentralDirOffset - V2_SIGNING_MAGIC.length()); 382 seek(mCentralDirOffset - V2_SIGNING_MAGIC.length());
378 String magic = readString(V2_SIGNING_MAGIC.length()); 383 String magic = readString(V2_SIGNING_MAGIC.length());
379 if (V2_SIGNING_MAGIC.equals(magic)) { 384 if (V2_SIGNING_MAGIC.equals(magic)) {
380 // Only if we have a v2 signature do we allow medium sized gap b etween the last 385 // Only if we have a v2 signature do we allow medium sized gap b etween the last
381 // block and the start of the central directory. 386 // block and the start of the central directory.
382 if (mCentralDirOffset - positionOfLastByteOfLastBlock > MAX_V2_S IGNING_BLOCK_SIZE) { 387 if (mCentralDirOffset - lastByte > MAX_V2_SIGNING_BLOCK_SIZE) {
383 return ERROR_BAD_V2_SIGNING_BLOCK; 388 return ERROR_BAD_V2_SIGNING_BLOCK;
384 } 389 }
385 } else { 390 } else {
386 return ERROR_BAD_BLANK_SPACE; 391 return ERROR_BAD_BLANK_SPACE;
387 } 392 }
388 } 393 }
389 return ERROR_OK; 394 return ERROR_OK;
390 } 395 }
391 396
392 /** 397 /**
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 return null; 466 return null;
462 } 467 }
463 byte[] data = new byte[len / 2]; 468 byte[] data = new byte[len / 2];
464 for (int i = 0; i < len; i += 2) { 469 for (int i = 0; i < len; i += 2) {
465 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) 470 data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
466 + Character.digit(s.charAt(i + 1), 16)); 471 + Character.digit(s.charAt(i + 1), 16));
467 } 472 }
468 return data; 473 return data;
469 } 474 }
470 } 475 }
OLDNEW
« no previous file with comments | « chrome/android/webapk/libs/client/junit/src/org/chromium/webapk/lib/client/WebApkValidatorTest.java ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698