Bläddra i källkod

Add SecureRandom (#473)

* Add SecureRandom
* Add CMake support for building src/support
Gil 8 år sedan
förälder
incheckning
5e49692058

+ 2 - 0
CMakeLists.txt

@@ -27,5 +27,7 @@ include_directories("${PROJECT_SOURCE_DIR}")
 # check target that
 add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure)
 
+include(cmake/utils.cmake)
+
 enable_testing()
 add_subdirectory(Firestore)

+ 3 - 0
Firestore/CMakeLists.txt

@@ -13,3 +13,6 @@
 # limitations under the License.
 
 include(${PROJECT_SOURCE_DIR}/cmake/external/googletest.cmake)
+
+add_subdirectory(src/support)
+add_subdirectory(test/support)

+ 13 - 1
Firestore/Example/Firestore.xcodeproj/project.pbxproj

@@ -24,6 +24,7 @@
 
 /* Begin PBXBuildFile section */
 		3B843E4C1F3A182900548890 /* remote_store_spec_test.json in Resources */ = {isa = PBXBuildFile; fileRef = 3B843E4A1F3930A400548890 /* remote_store_spec_test.json */; };
+		5463926E1FBEDE28005031AA /* secure_random_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 5463926D1FBEDE28005031AA /* secure_random_test.cc */; };
 		54764FAB1FAA0C320085E60A /* string_util_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAA1FAA0C320085E60A /* string_util_test.cc */; };
 		54764FAF1FAA21B90085E60A /* FSTGoogleTestTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */; };
 		5491BC721FB44593008B3588 /* FSTIntegrationTestCase.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5491BC711FB44593008B3588 /* FSTIntegrationTestCase.mm */; };
@@ -183,6 +184,7 @@
 		3B843E4A1F3930A400548890 /* remote_store_spec_test.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = remote_store_spec_test.json; sourceTree = "<group>"; };
 		42491D7DC8C8CD245CC22B93 /* Pods-SwiftBuildTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SwiftBuildTest.debug.xcconfig"; path = "Pods/Target Support Files/Pods-SwiftBuildTest/Pods-SwiftBuildTest.debug.xcconfig"; sourceTree = "<group>"; };
 		4EBC5F5ABE1FD097EFE5E224 /* Pods-Firestore_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Firestore_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Firestore_Example/Pods-Firestore_Example.release.xcconfig"; sourceTree = "<group>"; };
+		5463926D1FBEDE28005031AA /* secure_random_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = secure_random_test.cc; path = ../../test/support/secure_random_test.cc; sourceTree = "<group>"; };
 		54764FAA1FAA0C320085E60A /* string_util_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = string_util_test.cc; path = ../../Port/string_util_test.cc; sourceTree = "<group>"; };
 		54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = FSTGoogleTestTests.mm; path = GoogleTest/FSTGoogleTestTests.mm; sourceTree = "<group>"; };
 		5491BC711FB44593008B3588 /* FSTIntegrationTestCase.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FSTIntegrationTestCase.mm; sourceTree = "<group>"; };
@@ -364,11 +366,20 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+		5463926F1FBEDE2F005031AA /* support */ = {
+			isa = PBXGroup;
+			children = (
+				5463926D1FBEDE28005031AA /* secure_random_test.cc */,
+			);
+			name = support;
+			sourceTree = "<group>";
+		};
 		54764FAC1FAA0C390085E60A /* GoogleTests */ = {
 			isa = PBXGroup;
 			children = (
-				54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */,
 				54764FAD1FAA0C650085E60A /* Port */,
+				5463926F1FBEDE2F005031AA /* support */,
+				54764FAE1FAA21B90085E60A /* FSTGoogleTestTests.mm */,
 			);
 			name = GoogleTests;
 			sourceTree = "<group>";
@@ -1204,6 +1215,7 @@
 				DE51B1D91F0D490D0013853F /* FSTEagerGarbageCollectorTests.m in Sources */,
 				DE51B1E21F0D490D0013853F /* FSTMutationQueueTests.m in Sources */,
 				DE51B1E81F0D490D0013853F /* FSTLevelDBKeyTests.mm in Sources */,
+				5463926E1FBEDE28005031AA /* secure_random_test.cc in Sources */,
 				DE51B1E31F0D490D0013853F /* FSTPersistenceTestHelpers.m in Sources */,
 				DE51B1CF1F0D48CD0013853F /* FSTQueryListenerTests.m in Sources */,
 				DE51B1DA1F0D490D0013853F /* FSTLevelDBLocalStoreTests.m in Sources */,

+ 1 - 0
Firestore/Firestore.podspec

@@ -29,6 +29,7 @@ Google Cloud Firestore is a NoSQL document database built for automatic scaling,
     'Port/**/*',
     'Protos/objc/**/*.[hm]',
     'src/core/**/*.{h,cc}',
+    'src/support/**/*.{h,cc}',
     'third_party/**/*.[mh]'
   ]
   s.requires_arc = [

+ 18 - 0
Firestore/src/support/CMakeLists.txt

@@ -0,0 +1,18 @@
+# Copyright 2017 Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+add_library(
+  firestore_support
+  secure_random_arc4random.cc
+)

+ 33 - 0
Firestore/src/support/port.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FIRESTORE_SRC_SUPPORT_PORT_H_
+#define FIRESTORE_SRC_SUPPORT_PORT_H_
+
+#if defined(__APPLE__)
+// On Apple platforms we support building via Cocoapods without CMake. When
+// building this way we can't test the presence of features so predefine all
+// the platform-support feature macros to their expected values.
+
+// All supported Apple platforms have arc4random(3).
+#define HAVE_ARC4RANDOM 1
+
+#else
+
+#error "Unknown platform."
+#endif  // defined(__APPLE__)
+
+#endif  // FIRESTORE_SRC_SUPPORT_PORT_H_

+ 55 - 0
Firestore/src/support/secure_random.h

@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FIRESTORE_SRC_SUPPORT_SECURE_RANDOM_H_
+#define FIRESTORE_SRC_SUPPORT_SECURE_RANDOM_H_
+
+#include <stdint.h>
+
+#include <limits>
+
+namespace firestore {
+
+// A "secure" pseudorandom number generator, suitable for generating
+// unguessable identifiers. This exists because
+//
+//   * std::mt19937 is blazing fast but its outputs can be guessed once enough
+//     previous outputs have been observed.
+//   * std::random_device isn't guaranteed to come from a secure PRNG or be
+//     fast.
+//
+// The implementation satisfies the C++11 UniformRandomBitGenerator concept and
+// delegates to an implementation that generates high quality random values
+// quickly with periodic reseeding.
+class SecureRandom {
+ public:
+  // C++11 UniformRandomBitGenerator interface
+  using result_type = uint32_t;
+
+  static constexpr result_type min() {
+    return std::numeric_limits<result_type>::min();
+  }
+
+  static constexpr result_type max() {
+    return std::numeric_limits<result_type>::max();
+  }
+
+  result_type operator()();
+};
+
+}  // namespace firestore
+
+#endif  // FIRESTORE_SRC_SUPPORT_SECURE_RANDOM_H_

+ 33 - 0
Firestore/src/support/secure_random_arc4random.cc

@@ -0,0 +1,33 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/src/support/secure_random.h"
+
+#include "Firestore/src/support/port.h"
+
+#if HAVE_ARC4RANDOM
+
+#include <stdlib.h>
+
+namespace firestore {
+
+SecureRandom::result_type SecureRandom::operator()() {
+  return arc4random();
+}
+
+}  // namespace firestore
+
+#endif  // HAVE_ARC4RANDOM

+ 22 - 0
Firestore/test/support/CMakeLists.txt

@@ -0,0 +1,22 @@
+# Copyright 2017 Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cc_test(
+  firestore_support_test
+  secure_random_test.cc
+)
+target_link_libraries(
+  firestore_support_test
+  firestore_support
+)

+ 32 - 0
Firestore/test/support/secure_random_test.cc

@@ -0,0 +1,32 @@
+/*
+ * Copyright 2017 Google
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Firestore/src/support/secure_random.h"
+
+#include "gtest/gtest.h"
+
+using firestore::SecureRandom;
+
+TEST(SecureRandomTest, ResultsAreBounded) {
+  SecureRandom rng;
+
+  // Verify that values are on the min/max closed interval.
+  for (int i = 0; i < 1000; i++) {
+    SecureRandom::result_type value = rng();
+    EXPECT_GE(value, rng.min());
+    EXPECT_LE(value, rng.max());
+  }
+}

+ 29 - 0
cmake/utils.cmake

@@ -0,0 +1,29 @@
+# Copyright 2017 Google
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Defines a new test executable and does all the things we want done with
+# tests:
+#
+#   * add_executable (with the given arguments)
+#   * add_Test - defines a test with the same name
+#   * declares that the test links against gtest
+#   * adds the executable as a dependency of the `check` target.
+function(cc_test name)
+  add_executable(${name} ${ARGN})
+  add_test(${name} ${name})
+
+  target_link_libraries(${name} gtest gtest_main)
+
+  add_dependencies(check ${name})
+endfunction()