diff --git a/WORKSPACE b/WORKSPACE
index 04affb829041e59d0ac0f5e33bbc6644866af87d..087c9c7710b19e019f0debdcaed4b536dc89ac9d 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -2,8 +2,8 @@
 # third_party/rules_protobuf.
 git_repository(
     name = "org_pubref_rules_protobuf",
+    commit = "61efe7c69a6bafffd9f1231f9d6ea97c2014aa64",
     remote = "https://github.com/pubref/rules_protobuf.git",
-    tag = "v0.7.2",
 )
 
 # go packages
@@ -12,17 +12,19 @@ git_repository(
     remote = "https://github.com/bazelbuild/rules_go.git",
     tag = "0.4.4",
 )
+
 load("@io_bazel_rules_go//go:def.bzl", "go_repositories", "new_go_repository")
 load("@io_bazel_rules_go//proto:go_proto_library.bzl", "go_proto_repositories")
 
 go_repositories()
+
 go_proto_repositories()
 
 # wycheproof
 http_archive(
     name = "wycheproof",
-    strip_prefix = "wycheproof-f755ff0279ddd5fa26640d959d5872764b45feb7",
     sha256 = "8b32637abcf0c775dac424894a6586a75df821a7ffeedc467ccffa29209683e5",
+    strip_prefix = "wycheproof-f755ff0279ddd5fa26640d959d5872764b45feb7",
     url = "https://github.com/google/wycheproof/archive/f755ff0279ddd5fa26640d959d5872764b45feb7.zip",
 )
 
@@ -45,36 +47,36 @@ new_git_repository(
 # This statement defines the @com_google_protobuf repo.
 http_archive(
     name = "com_google_protobuf",
+    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
     strip_prefix = "protobuf-3.3.0",
     urls = ["https://github.com/google/protobuf/archive/v3.3.0.tar.gz"],
-    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
 )
 
 # cc_proto_library rules implicitly depend on @com_google_protobuf_cc//:cc_toolchain,
 # which is the C++ proto runtime (base classes and common utilities).
 http_archive(
     name = "com_google_protobuf_cc",
+    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
     strip_prefix = "protobuf-3.3.0",
     urls = ["https://github.com/google/protobuf/archive/v3.3.0.tar.gz"],
-    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
 )
 
 # java_proto_library rules implicitly depend on @com_google_protobuf_java//:java_toolchain,
 # which is the Java proto runtime (base classes and common utilities).
 http_archive(
     name = "com_google_protobuf_java",
+    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
     strip_prefix = "protobuf-3.3.0",
     urls = ["https://github.com/google/protobuf/archive/v3.3.0.tar.gz"],
-    sha256 = "94c414775f275d876e5e0e4a276527d155ab2d0da45eed6b7734301c330be36e",
 )
 
 # java_lite_proto_library rules implicitly depend on @com_google_protobuf_javalite//:javalite_toolchain,
 # which is the JavaLite proto runtime (base classes and common utilities).
 http_archive(
     name = "com_google_protobuf_javalite",
+    sha256 = "b9ca3f706c6a6a6a744a7ba85321abce9e7d49825a19aaba6f29278871d41926",
     strip_prefix = "protobuf-javalite",
     urls = ["https://github.com/google/protobuf/archive/javalite.zip"],
-    sha256 = "b9ca3f706c6a6a6a744a7ba85321abce9e7d49825a19aaba6f29278871d41926",
 )
 
 # objc_proto_library rules from @org_pubref_rules_protobuf require the objective
diff --git a/kokoro/macos_external/presubmit.sh b/kokoro/macos_external/presubmit.sh
index 86ccd0677eda3e8ceffd84c9c4bc89d2376f7bec..ee32f62908a7d807427d7c7097d9ba9f195b690d 100755
--- a/kokoro/macos_external/presubmit.sh
+++ b/kokoro/macos_external/presubmit.sh
@@ -54,8 +54,8 @@ ${BAZEL_BIN} version
 echo "using java binary: " `which java`
 java -version
 
-# Test the iOS targets.
-${BAZEL_BIN} test \
+# Build all the iOS targets.
+${BAZEL_BIN} build \
   $DISABLE_SANDBOX \
   --compilation_mode=dbg \
   --dynamic_mode=off \
diff --git a/proto/BUILD b/proto/BUILD
index c49bba44184b99c5c31111b79cbd257863712fea..59ea8bc41f743ce31eeb453d82bce0a141ac7382 100644
--- a/proto/BUILD
+++ b/proto/BUILD
@@ -10,6 +10,8 @@ package(
 licenses(["notice"])  # Apache 2.0
 
 load("@io_bazel_rules_go//proto:go_proto_library.bzl", "go_proto_library")
+load("@org_pubref_rules_protobuf//objc:rules.bzl", "objc_proto_compile")
+load("//proto:objc.bzl", "tink_objc_proto_library")
 
 # -----------------------------------------------
 # common
@@ -43,6 +45,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "common_objc_pb",
+    protos = ["common.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # tink
 # -----------------------------------------------
@@ -81,6 +91,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "tink_objc_pb",
+    protos = ["tink.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # ecdsa
 # -----------------------------------------------
@@ -119,6 +137,15 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "ecdsa_objc_pb",
+    protos = ["ecdsa.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [":common_objc_pb"],
+)
+
 # -----------------------------------------------
 # ed25519
 # -----------------------------------------------
@@ -151,6 +178,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "ed25519_objc_pb",
+    protos = ["ed25519.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # hmac
 # -----------------------------------------------
@@ -187,6 +222,15 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "hmac_objc_pb",
+    protos = ["hmac.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [":common_objc_pb"],
+)
+
 # -----------------------------------------------
 # aes_ctr
 # -----------------------------------------------
@@ -219,6 +263,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_ctr_objc_pb",
+    protos = ["aes_ctr.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # aes_ctr_hmac_aead
 # -----------------------------------------------
@@ -259,6 +311,18 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_ctr_hmac_aead_objc_pb",
+    protos = ["aes_ctr_hmac_aead.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [
+        ":aes_ctr_objc_pb",
+        ":hmac_objc_pb",
+    ],
+)
+
 # -----------------------------------------------
 # aes_gcm
 # -----------------------------------------------
@@ -291,6 +355,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_gcm_objc_pb",
+    protos = ["aes_gcm.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # aes_ctr_hmac_streaming
 # -----------------------------------------------
@@ -329,6 +401,18 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_ctr_hmac_streaming_objc_pb",
+    protos = ["aes_ctr_hmac_streaming.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [
+        ":common_objc_pb",
+        ":hmac_objc_pb",
+    ],
+)
+
 # -----------------------------------------------
 # aes_gcm_hkdf_streaming
 # -----------------------------------------------
@@ -363,6 +447,17 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_gcm_hkdf_streaming_objc_pb",
+    protos = ["aes_gcm_hkdf_streaming.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [
+        ":common_objc_pb",
+    ],
+)
+
 # -----------------------------------------------
 # aes_eax
 # -----------------------------------------------
@@ -395,6 +490,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "aes_eax_objc_pb",
+    protos = ["aes_eax.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # chacha20_poly1305
 # -----------------------------------------------
@@ -427,6 +530,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "chacha20_poly1305_objc_pb",
+    protos = ["chacha20_poly1305.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # kms_aead
 # -----------------------------------------------
@@ -459,6 +570,14 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "kms_aead_objc_pb",
+    protos = ["kms_aead.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+)
+
 # -----------------------------------------------
 # kms_envelope
 # -----------------------------------------------
@@ -495,6 +614,17 @@ go_proto_library(
     ],
 )
 
+objc_proto_compile(
+    name = "kms_envelope_objc_pb",
+    protos = ["kms_envelope.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [
+        ":tink_objc_pb",
+    ],
+)
+
 # -----------------------------------------------
 # ecies_aead_hkdf
 # -----------------------------------------------
@@ -534,3 +664,40 @@ go_proto_library(
         ":tink_go_proto",
     ],
 )
+
+objc_proto_compile(
+    name = "ecies_aead_hkdf_objc_pb",
+    protos = ["ecies_aead_hkdf.proto"],
+    tags = ["manual"],
+    visibility = ["//visibility:private"],
+    with_grpc = False,
+    deps = [
+        ":common_objc_pb",
+        ":tink_objc_pb",
+    ],
+)
+
+# -----------------------------------------------
+# objc library
+# -----------------------------------------------
+tink_objc_proto_library(
+    name = "all_objc_proto",
+    srcs = [
+        ":aes_ctr_hmac_aead_objc_pb",
+        ":aes_ctr_hmac_streaming_objc_pb",
+        ":aes_ctr_objc_pb",
+        ":aes_eax_objc_pb",
+        ":aes_gcm_hkdf_streaming_objc_pb",
+        ":aes_gcm_objc_pb",
+        ":chacha20_poly1305_objc_pb",
+        ":common_objc_pb",
+        ":ecdsa_objc_pb",
+        ":ecies_aead_hkdf_objc_pb",
+        ":ed25519_objc_pb",
+        ":hmac_objc_pb",
+        ":kms_aead_objc_pb",
+        ":kms_envelope_objc_pb",
+        ":tink_objc_pb",
+    ],
+    tags = ["manual"],
+)
diff --git a/proto/aes_ctr.proto b/proto/aes_ctr.proto
index 46ff119ecaf131de773fbbe9fb251823ca72c2fd..e56ad20f6b8a4d50e55b4c2be06c9d9a38b450e6 100644
--- a/proto/aes_ctr.proto
+++ b/proto/aes_ctr.proto
@@ -20,6 +20,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message AesCtrParams {
   uint32 iv_size = 1;
diff --git a/proto/aes_ctr_hmac_aead.proto b/proto/aes_ctr_hmac_aead.proto
index 4e840ec639d732d403d55a5a8d49a79edef7b999..d29a7e8aef0585c431c08f57a0d4514f01f80fc0 100644
--- a/proto/aes_ctr_hmac_aead.proto
+++ b/proto/aes_ctr_hmac_aead.proto
@@ -23,6 +23,7 @@ import "proto/hmac.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message AesCtrHmacAeadParams {
   AesCtrParams aes_ctr_params = 1;
diff --git a/proto/aes_ctr_hmac_streaming.proto b/proto/aes_ctr_hmac_streaming.proto
index f6205dc3453f827b71ebe41cf47986c47a56c64d..149fcb3cfdaaea89044c99f61313813c250c7422 100644
--- a/proto/aes_ctr_hmac_streaming.proto
+++ b/proto/aes_ctr_hmac_streaming.proto
@@ -23,6 +23,7 @@ import "proto/hmac.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message AesCtrHmacStreamingParams {
   uint32 ciphertext_segment_size = 1;
diff --git a/proto/aes_eax.proto b/proto/aes_eax.proto
index ba7895a91e471d57d041189a901183495048823a..c6ce11bdaf32e39fbe06ce1a1075f4a33bc69bb9 100644
--- a/proto/aes_eax.proto
+++ b/proto/aes_eax.proto
@@ -20,6 +20,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // only allowing tag size in bytes = 16
 message AesEaxParams {
diff --git a/proto/aes_gcm.proto b/proto/aes_gcm.proto
index 4db1a6faa00ec58d2f4ec5d6c6f5ea16e1867a42..c3055483ec033d6637022e85dc839f705f955fd2 100644
--- a/proto/aes_gcm.proto
+++ b/proto/aes_gcm.proto
@@ -20,6 +20,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // only allowing IV size in bytes = 12 and tag size in bytes = 16
 // Thus, accept no params.
diff --git a/proto/aes_gcm_hkdf_streaming.proto b/proto/aes_gcm_hkdf_streaming.proto
index 4b0756c4fd5431b3569763c7348bec472f023f6c..a167ac25a12ef5927b34b070ed1c0b70a50d5105 100644
--- a/proto/aes_gcm_hkdf_streaming.proto
+++ b/proto/aes_gcm_hkdf_streaming.proto
@@ -23,6 +23,7 @@ import "proto/common.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message AesGcmHkdfStreamingParams {
   uint32 ciphertext_segment_size = 1;
diff --git a/proto/chacha20_poly1305.proto b/proto/chacha20_poly1305.proto
index e26289fe5588ab6d8fe9d03d1b534dc9b5f61688..530509a8cd85ef5226a27c13fb4654534c446447 100644
--- a/proto/chacha20_poly1305.proto
+++ b/proto/chacha20_poly1305.proto
@@ -20,6 +20,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // key_type: type.googleapis.com/google.crypto.tink.ChaCha20Poly1305.
 // This key type actually implements ChaCha20Poly1305 as described
diff --git a/proto/common.proto b/proto/common.proto
index 922828c2a66d4c4528c4c7612dedee6b0a847732..1d857cffbc654cd8beb76abb170b12498421b6fb 100644
--- a/proto/common.proto
+++ b/proto/common.proto
@@ -21,6 +21,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 enum EllipticCurveType {
   UNKNOWN_CURVE = 0;
diff --git a/proto/ecdsa.proto b/proto/ecdsa.proto
index 34be65ba46e50fd41cf3bac184cddf157cbd246a..e6591a7a13b1fd36071f9f9cf214b7b5b55938b1 100644
--- a/proto/ecdsa.proto
+++ b/proto/ecdsa.proto
@@ -22,6 +22,7 @@ import "proto/common.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 enum EcdsaSignatureEncoding {
   UNKNOWN_ENCODING = 0;
diff --git a/proto/ecies_aead_hkdf.proto b/proto/ecies_aead_hkdf.proto
index dd7d34461cc78124db344e66990e97af952dc3f3..c503d585f84bcd63f55cd55897b0d50e216c3d18 100644
--- a/proto/ecies_aead_hkdf.proto
+++ b/proto/ecies_aead_hkdf.proto
@@ -23,6 +23,7 @@ import "proto/tink.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // Protos for keys for ECIES with HKDF and AEAD encryption.
 //
diff --git a/proto/ed25519.proto b/proto/ed25519.proto
index c9ac2f62880866fca3a728476b8f9e24ae0e633f..b1523d5bb4ae7262b202b0a67e09256c123001fb 100644
--- a/proto/ed25519.proto
+++ b/proto/ed25519.proto
@@ -23,6 +23,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // key_type: type.googleapis.com/google.crypto.tink.Ed25519PublicKey
 message Ed25519PublicKey {
diff --git a/proto/hmac.proto b/proto/hmac.proto
index 10caed1af1efe05f45e4bb384ddf5375dd96fd4c..fbcd1d2223388f60454a6daf72ab9ffb55cccef0 100644
--- a/proto/hmac.proto
+++ b/proto/hmac.proto
@@ -22,6 +22,7 @@ import "proto/common.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message HmacParams {
   HashType hash = 1;    // HashType is an enum.
diff --git a/proto/kms_aead.proto b/proto/kms_aead.proto
index 0bcb1b0977b9d1f567e6edad8f2db5c7d88fe884..7e1e811f9bd92ee74629eb66f0322e7c51159560 100644
--- a/proto/kms_aead.proto
+++ b/proto/kms_aead.proto
@@ -20,6 +20,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message KmsAeadKeyFormat {
   // Required.
diff --git a/proto/kms_envelope.proto b/proto/kms_envelope.proto
index d1e377b8070c3c7cdb31689e62c7682e7a0b5950..0e9360c2a389072cdd5ec34d7d4dad7861a8fa6e 100644
--- a/proto/kms_envelope.proto
+++ b/proto/kms_envelope.proto
@@ -22,6 +22,7 @@ import "proto/tink.proto";
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 message KmsEnvelopeAeadKeyFormat {
   // Required.
diff --git a/proto/objc.bzl b/proto/objc.bzl
new file mode 100644
index 0000000000000000000000000000000000000000..b7ef1583844be66bce2432bc366adcdc84aded19
--- /dev/null
+++ b/proto/objc.bzl
@@ -0,0 +1,42 @@
+# The actual rule which does the filtering.
+def _do_filter_impl(ctx):
+  return struct(
+    files = set([f for f in ctx.files.srcs if f.path.endswith(ctx.attr.suffix)]),
+  )
+
+_do_filter = rule(
+    attrs = {
+        "srcs": attr.label_list(
+            mandatory = True,
+            allow_files = True,
+        ),
+        "suffix": attr.string(
+            mandatory = True,
+        ),
+    },
+    implementation = _do_filter_impl,
+)
+
+# A convenient macro to wrap the custom rule and objc_library.
+def tink_objc_proto_library(name, srcs, **kwargs):
+  _do_filter(
+    name = "%s_hdrs" % name,
+    visibility = ["//visibility:private"],
+    # srcs = hdrs,
+    srcs = srcs,
+    suffix = ".pbobjc.h",
+  )
+  _do_filter(
+    name = "%s_srcs" % name,
+    visibility = ["//visibility:private"],
+    srcs = srcs,
+    suffix = ".pbobjc.m",
+  )
+  native.objc_library(
+    name = name,
+    srcs = [ ":%s_srcs" % name ],
+    hdrs = [ ":%s_hdrs" % name ],
+    copts = [ "-fno-objc-arc" ],
+    deps = [ "@com_google_protobuf_objc//:objectivec" ],
+    **kwargs
+  )
diff --git a/proto/tink.proto b/proto/tink.proto
index a306b816ab0eb0f03861188bdabe476f0dafc126..bc33818ef2f413b30ade0e29780f5928d0d092d4 100644
--- a/proto/tink.proto
+++ b/proto/tink.proto
@@ -21,6 +21,7 @@ package google.crypto.tink;
 
 option java_package = "com.google.crypto.tink.proto";
 option java_multiple_files = true;
+option objc_class_prefix = "TINKPB";
 
 // Each instantiation of a Tink primitive is identified by type_url,
 // which is a global URL pointing to a *Key-proto that holds key material