Commit 89299435 authored by Travis Skare's avatar Travis Skare Committed by Commit Bot

[QR Generator] Move webauthn QR encoder to common/

This is towards servicification.

Bug: 1050259
Change-Id: Ia32c670da08b2026b46b8e64030e1f2054a19a22
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2045136
Commit-Queue: Travis Skare <skare@chromium.org>
Reviewed-by: default avatarDavid Trainor <dtrainor@chromium.org>
Reviewed-by: default avatarAdam Langley <agl@chromium.org>
Cr-Commit-Position: refs/heads/master@{#742798}
parent b67e52a0
...@@ -3379,8 +3379,6 @@ jumbo_static_library("ui") { ...@@ -3379,8 +3379,6 @@ jumbo_static_library("ui") {
"views/webauthn/authenticator_client_pin_entry_sheet_view.h", "views/webauthn/authenticator_client_pin_entry_sheet_view.h",
"views/webauthn/authenticator_client_pin_entry_view.cc", "views/webauthn/authenticator_client_pin_entry_view.cc",
"views/webauthn/authenticator_client_pin_entry_view.h", "views/webauthn/authenticator_client_pin_entry_view.h",
"views/webauthn/authenticator_qr_code.cc",
"views/webauthn/authenticator_qr_code.h",
"views/webauthn/authenticator_qr_sheet_view.cc", "views/webauthn/authenticator_qr_sheet_view.cc",
"views/webauthn/authenticator_qr_sheet_view.h", "views/webauthn/authenticator_qr_sheet_view.h",
"views/webauthn/authenticator_request_dialog_view.cc", "views/webauthn/authenticator_request_dialog_view.cc",
...@@ -3418,6 +3416,7 @@ jumbo_static_library("ui") { ...@@ -3418,6 +3416,7 @@ jumbo_static_library("ui") {
deps += [ deps += [
"//chrome/browser/ui/views", "//chrome/browser/ui/views",
"//chrome/common/qr_code_generator",
"//components/constrained_window", "//components/constrained_window",
"//components/media_message_center", "//components/media_message_center",
"//components/payments/content", "//components/payments/content",
......
...@@ -7,13 +7,13 @@ ...@@ -7,13 +7,13 @@
#include "base/base64url.h" #include "base/base64url.h"
#include "base/rand_util.h" #include "base/rand_util.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "chrome/browser/ui/views/webauthn/authenticator_qr_code.h" #include "chrome/common/qr_code_generator/qr_code_generator.h"
#include "device/fido/cable/cable_discovery_data.h" #include "device/fido/cable/cable_discovery_data.h"
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/views/layout/box_layout.h" #include "ui/views/layout/box_layout.h"
#include "ui/views/view.h" #include "ui/views/view.h"
using QRCode = AuthenticatorQRCode; using QRCode = QRCodeGenerator;
namespace { namespace {
......
...@@ -195,6 +195,7 @@ static_library("common") { ...@@ -195,6 +195,7 @@ static_library("common") {
"//chrome/common:constants", "//chrome/common:constants",
"//chrome/common/net", "//chrome/common/net",
"//chrome/common/profiler", "//chrome/common/profiler",
"//chrome/common/qr_code_generator",
"//chrome/installer/util:with_no_strings", "//chrome/installer/util:with_no_strings",
"//components/cast_certificate", "//components/cast_certificate",
"//components/cdm/common", "//components/cdm/common",
......
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("qr_code_generator") {
sources = [
"qr_code_generator.cc",
"qr_code_generator.h",
]
deps = [ "//base" ]
public_deps = [ "//base" ]
}
file://device/fido/OWNERS
# TEAM: identity-dev@chromium.org
# COMPONENT: Blink>WebAuthentication
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/views/webauthn/authenticator_qr_code.h" #include "chrome/common/qr_code_generator/qr_code_generator.h"
#include <string.h> #include <string.h>
#include "base/logging.h" #include "base/logging.h"
static_assert(AuthenticatorQRCode::kNumSegments != 0 && static_assert(QRCodeGenerator::kNumSegments != 0 &&
AuthenticatorQRCode::kTotalBytes % QRCodeGenerator::kTotalBytes %
AuthenticatorQRCode::kNumSegments == QRCodeGenerator::kNumSegments ==
0, 0,
"invalid configuration"); "invalid configuration");
// Generate generates a QR code containing the given data and returns a // Generate generates a QR code containing the given data and returns a
// pointer to an array of kSize×kSize bytes where the least-significant bit of // pointer to an array of kSize×kSize bytes where the least-significant bit of
// each byte is set if that tile should be "black". // each byte is set if that tile should be "black".
base::span<const uint8_t, AuthenticatorQRCode::kTotalSize> base::span<const uint8_t, QRCodeGenerator::kTotalSize>
AuthenticatorQRCode::Generate(const uint8_t in[kInputBytes]) { QRCodeGenerator::Generate(const uint8_t in[kInputBytes]) {
memset(d_, 0, sizeof(d_)); memset(d_, 0, sizeof(d_));
PutVerticalTiming(6); PutVerticalTiming(6);
PutHorizontalTiming(6); PutHorizontalTiming(6);
...@@ -79,12 +79,12 @@ AuthenticatorQRCode::Generate(const uint8_t in[kInputBytes]) { ...@@ -79,12 +79,12 @@ AuthenticatorQRCode::Generate(const uint8_t in[kInputBytes]) {
// MaskFunction3 implements one of the data-masking functions. See figure 21. // MaskFunction3 implements one of the data-masking functions. See figure 21.
// static // static
uint8_t AuthenticatorQRCode::MaskFunction3(int x, int y) { uint8_t QRCodeGenerator::MaskFunction3(int x, int y) {
return (x + y) % 3 == 0; return (x + y) % 3 == 0;
} }
// PutFinder paints a finder symbol at the given coordinates. // PutFinder paints a finder symbol at the given coordinates.
void AuthenticatorQRCode::PutFinder(int x, int y) { void QRCodeGenerator::PutFinder(int x, int y) {
DCHECK_GE(x, 3); DCHECK_GE(x, 3);
DCHECK_GE(y, 3); DCHECK_GE(y, 3);
fillAt(x - 3, y - 3, 7, 0b11); fillAt(x - 3, y - 3, 7, 0b11);
...@@ -114,7 +114,7 @@ void AuthenticatorQRCode::PutFinder(int x, int y) { ...@@ -114,7 +114,7 @@ void AuthenticatorQRCode::PutFinder(int x, int y) {
} }
// PutAlignment paints an alignment symbol centered at the given coordinates. // PutAlignment paints an alignment symbol centered at the given coordinates.
void AuthenticatorQRCode::PutAlignment(int x, int y) { void QRCodeGenerator::PutAlignment(int x, int y) {
fillAt(x - 2, y - 2, 5, 0b11); fillAt(x - 2, y - 2, 5, 0b11);
fillAt(x - 2, y + 2, 5, 0b11); fillAt(x - 2, y + 2, 5, 0b11);
static constexpr uint8_t kLine[5] = {0b11, 0b10, 0b10, 0b10, 0b11}; static constexpr uint8_t kLine[5] = {0b11, 0b10, 0b10, 0b10, 0b11};
...@@ -125,14 +125,14 @@ void AuthenticatorQRCode::PutAlignment(int x, int y) { ...@@ -125,14 +125,14 @@ void AuthenticatorQRCode::PutAlignment(int x, int y) {
} }
// PutVerticalTiming paints the vertical timing signal. // PutVerticalTiming paints the vertical timing signal.
void AuthenticatorQRCode::PutVerticalTiming(int x) { void QRCodeGenerator::PutVerticalTiming(int x) {
for (int y = 0; y < kSize; y++) { for (int y = 0; y < kSize; y++) {
at(x, y) = 0b10 | (1 ^ (y & 1)); at(x, y) = 0b10 | (1 ^ (y & 1));
} }
} }
// PutVerticalTiming paints the horizontal timing signal. // PutVerticalTiming paints the horizontal timing signal.
void AuthenticatorQRCode::PutHorizontalTiming(int y) { void QRCodeGenerator::PutHorizontalTiming(int y) {
for (int x = 0; x < kSize; x++) { for (int x = 0; x < kSize; x++) {
at(x, y) = 0b10 | (1 ^ (x & 1)); at(x, y) = 0b10 | (1 ^ (x & 1));
} }
...@@ -140,7 +140,7 @@ void AuthenticatorQRCode::PutHorizontalTiming(int y) { ...@@ -140,7 +140,7 @@ void AuthenticatorQRCode::PutHorizontalTiming(int y) {
// PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56 // PutFormatBits paints the 15-bit, pre-encoded format metadata. See page 56
// for the location of the format bits. // for the location of the format bits.
void AuthenticatorQRCode::PutFormatBits(const uint16_t format) { void QRCodeGenerator::PutFormatBits(const uint16_t format) {
// kRun1 is the location of the initial format bits, where the upper nibble // kRun1 is the location of the initial format bits, where the upper nibble
// is the x coordinate and the lower the y. // is the x coordinate and the lower the y.
static constexpr uint8_t kRun1[15] = { static constexpr uint8_t kRun1[15] = {
...@@ -171,9 +171,9 @@ void AuthenticatorQRCode::PutFormatBits(const uint16_t format) { ...@@ -171,9 +171,9 @@ void AuthenticatorQRCode::PutFormatBits(const uint16_t format) {
// PutBits writes the given data into the QR code in correct order, avoiding // PutBits writes the given data into the QR code in correct order, avoiding
// structural elements that must have already been painted. See section 7.7.3 // structural elements that must have already been painted. See section 7.7.3
// about the placement algorithm. // about the placement algorithm.
void AuthenticatorQRCode::PutBits(const uint8_t* data, void QRCodeGenerator::PutBits(const uint8_t* data,
size_t data_len, size_t data_len,
uint8_t (*mask_func)(int, int)) { uint8_t (*mask_func)(int, int)) {
// BitStream vends bits from |data| on demand, in the order that QR codes // BitStream vends bits from |data| on demand, in the order that QR codes
// expect them. // expect them.
class BitStream { class BitStream {
...@@ -245,7 +245,7 @@ void AuthenticatorQRCode::PutBits(const uint8_t* data, ...@@ -245,7 +245,7 @@ void AuthenticatorQRCode::PutBits(const uint8_t* data,
} }
// at returns a reference to the given element of |d_|. // at returns a reference to the given element of |d_|.
uint8_t& AuthenticatorQRCode::at(int x, int y) { uint8_t& QRCodeGenerator::at(int x, int y) {
DCHECK_LE(0, x); DCHECK_LE(0, x);
DCHECK_LT(x, kSize); DCHECK_LT(x, kSize);
DCHECK_LE(0, y); DCHECK_LE(0, y);
...@@ -254,7 +254,7 @@ uint8_t& AuthenticatorQRCode::at(int x, int y) { ...@@ -254,7 +254,7 @@ uint8_t& AuthenticatorQRCode::at(int x, int y) {
} }
// fillAt sets the |len| elements at (x, y) to |value|. // fillAt sets the |len| elements at (x, y) to |value|.
void AuthenticatorQRCode::fillAt(int x, int y, size_t len, uint8_t value) { void QRCodeGenerator::fillAt(int x, int y, size_t len, uint8_t value) {
DCHECK_LE(0, x); DCHECK_LE(0, x);
DCHECK_LE(static_cast<int>(x + len), kSize); DCHECK_LE(static_cast<int>(x + len), kSize);
DCHECK_LE(0, y); DCHECK_LE(0, y);
...@@ -263,10 +263,7 @@ void AuthenticatorQRCode::fillAt(int x, int y, size_t len, uint8_t value) { ...@@ -263,10 +263,7 @@ void AuthenticatorQRCode::fillAt(int x, int y, size_t len, uint8_t value) {
} }
// copyTo copies |len| elements from |data| to the elements at (x, y). // copyTo copies |len| elements from |data| to the elements at (x, y).
void AuthenticatorQRCode::copyTo(int x, void QRCodeGenerator::copyTo(int x, int y, const uint8_t* data, size_t len) {
int y,
const uint8_t* data,
size_t len) {
DCHECK_LE(0, x); DCHECK_LE(0, x);
DCHECK_LE(static_cast<int>(x + len), kSize); DCHECK_LE(static_cast<int>(x + len), kSize);
DCHECK_LE(0, y); DCHECK_LE(0, y);
...@@ -276,7 +273,7 @@ void AuthenticatorQRCode::copyTo(int x, ...@@ -276,7 +273,7 @@ void AuthenticatorQRCode::copyTo(int x,
// clipped returns a reference to the given element of |d_|, or to // clipped returns a reference to the given element of |d_|, or to
// |clip_dump_| if the coordinates are out of bounds. // |clip_dump_| if the coordinates are out of bounds.
uint8_t& AuthenticatorQRCode::clipped(int x, int y) { uint8_t& QRCodeGenerator::clipped(int x, int y) {
if (0 <= x && x < kSize && 0 <= y && y < kSize) { if (0 <= x && x < kSize && 0 <= y && y < kSize) {
return d_[kSize * y + x]; return d_[kSize * y + x];
} }
...@@ -286,7 +283,7 @@ uint8_t& AuthenticatorQRCode::clipped(int x, int y) { ...@@ -286,7 +283,7 @@ uint8_t& AuthenticatorQRCode::clipped(int x, int y) {
// GF28Mul returns the product of |a| and |b| (which must be field elements, // GF28Mul returns the product of |a| and |b| (which must be field elements,
// i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1. // i.e. < 256) in the field GF(2^8) mod x^8 + x^4 + x^3 + x^2 + 1.
// static // static
uint8_t AuthenticatorQRCode::GF28Mul(uint16_t a, uint16_t b) { uint8_t QRCodeGenerator::GF28Mul(uint16_t a, uint16_t b) {
uint16_t acc = 0; uint16_t acc = 0;
// Perform 8-bit, carry-less multiplication of |a| and |b|. // Perform 8-bit, carry-less multiplication of |a| and |b|.
...@@ -313,9 +310,8 @@ uint8_t AuthenticatorQRCode::GF28Mul(uint16_t a, uint16_t b) { ...@@ -313,9 +310,8 @@ uint8_t AuthenticatorQRCode::GF28Mul(uint16_t a, uint16_t b) {
// AddErrorCorrection writes the Reed-Solomon expanded version of |in| to // AddErrorCorrection writes the Reed-Solomon expanded version of |in| to
// |out|. // |out|.
// static // static
void AuthenticatorQRCode::AddErrorCorrection( void QRCodeGenerator::AddErrorCorrection(uint8_t out[kSegmentBytes],
uint8_t out[kSegmentBytes], const uint8_t in[kSegmentDataBytes]) {
const uint8_t in[kSegmentDataBytes]) {
// kGenerator is the product of (z - x^i) for 0 <= i < |kSegmentECBytes|, // kGenerator is the product of (z - x^i) for 0 <= i < |kSegmentECBytes|,
// where x is the term of GF(2^8) and z is the term of a polynomial ring // where x is the term of GF(2^8) and z is the term of a polynomial ring
// over GF(2^8). It's generated with the following Sage script: // over GF(2^8). It's generated with the following Sage script:
......
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_QR_CODE_H_ #ifndef CHROME_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_QR_CODE_H_ #define CHROME_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "base/containers/span.h" #include "base/containers/span.h"
// AuthenticatorQRCode generates version three, class Q QR codes that carry 32 // QRCodeGenerator generates version three, class Q QR codes that carry 32
// bytes of raw data. References in the following comments refer to ISO 18004 // bytes of raw data. References in the following comments refer to ISO 18004
// (3rd edition). // (3rd edition).
class AuthenticatorQRCode { class QRCodeGenerator {
public: public:
// kSize is the number of "tiles" in each dimension for a v3 QR code. See // kSize is the number of "tiles" in each dimension for a v3 QR code. See
// table 1. (The colored squares in in QR codes are called tiles in the // table 1. (The colored squares in in QR codes are called tiles in the
...@@ -98,4 +98,4 @@ class AuthenticatorQRCode { ...@@ -98,4 +98,4 @@ class AuthenticatorQRCode {
uint8_t clip_dump_; uint8_t clip_dump_;
}; };
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_QR_CODE_H_ #endif // CHROME_COMMON_QR_CODE_GENERATOR_QR_CODE_GENERATOR_H_
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/ui/views/webauthn/authenticator_qr_code.h" #include "chrome/common/qr_code_generator/qr_code_generator.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
TEST(AuthenticatorQRCode, Generate) { TEST(QRCodeGenerator, Generate) {
// Without a QR decoder implementation, there's a limit to how much we can // Without a QR decoder implementation, there's a limit to how much we can
// test the QR encoder. Therefore this test just runs a generation to ensure // test the QR encoder. Therefore this test just runs a generation to ensure
// that no DCHECKs are hit and that the output has the correct structure. When // that no DCHECKs are hit and that the output has the correct structure. When
// run under ASan, this will also check that every byte of the output has been // run under ASan, this will also check that every byte of the output has been
// written to. // written to.
AuthenticatorQRCode qr; QRCodeGenerator qr;
uint8_t input[AuthenticatorQRCode::kInputBytes]; uint8_t input[QRCodeGenerator::kInputBytes];
memset(input, 'a', sizeof(input)); memset(input, 'a', sizeof(input));
auto qr_data = qr.Generate(input); auto qr_data = qr.Generate(input);
int index = 0; int index = 0;
for (int y = 0; y < AuthenticatorQRCode::kSize; y++) { for (int y = 0; y < QRCodeGenerator::kSize; y++) {
for (int x = 0; x < AuthenticatorQRCode::kSize; x++) { for (int x = 0; x < QRCodeGenerator::kSize; x++) {
ASSERT_EQ(0, qr_data[index++] & 0b11111100); ASSERT_EQ(0, qr_data[index++] & 0b11111100);
} }
} }
......
...@@ -1350,7 +1350,6 @@ if (!is_android) { ...@@ -1350,7 +1350,6 @@ if (!is_android) {
"../browser/ui/views/web_apps/web_app_minimal_ui_test.cc", "../browser/ui/views/web_apps/web_app_minimal_ui_test.cc",
"../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc", "../browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc",
"../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc", "../browser/ui/views/webauthn/authenticator_dialog_view_browsertest.cc",
"../browser/ui/views/webauthn/authenticator_qr_code_test.cc",
"../browser/ui/views/webview_accessibility_browsertest.cc", "../browser/ui/views/webview_accessibility_browsertest.cc",
"../browser/ui/web_applications/app_browser_controller_browsertest.cc", "../browser/ui/web_applications/app_browser_controller_browsertest.cc",
"../browser/ui/web_applications/create_shortcut_browsertest.cc", "../browser/ui/web_applications/create_shortcut_browsertest.cc",
...@@ -3531,6 +3530,7 @@ test("unit_tests") { ...@@ -3531,6 +3530,7 @@ test("unit_tests") {
"../common/origin_trials/chrome_origin_trial_policy_unittest.cc", "../common/origin_trials/chrome_origin_trial_policy_unittest.cc",
"../common/pref_names_util_unittest.cc", "../common/pref_names_util_unittest.cc",
"../common/profiler/thread_profiler_unittest.cc", "../common/profiler/thread_profiler_unittest.cc",
"../common/qr_code_generator/qr_code_generator_unittest.cc",
"../common/string_matching/fuzzy_tokenized_string_match_unittest.cc", "../common/string_matching/fuzzy_tokenized_string_match_unittest.cc",
"../common/string_matching/sequence_matcher_unittest.cc", "../common/string_matching/sequence_matcher_unittest.cc",
"../common/string_matching/term_break_iterator_unittest.cc", "../common/string_matching/term_break_iterator_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment