chaps: Return CKR_BUFFER_TOO_SMALL if a buffer was provided by the user

As per PKCS#11 s11.2:
 - if the output buffer is NULL, the return code should be CKR_OK
 - if the output buffer is present but too small, the return code should be
   CKR_BUFFER_TOO_SMALL

BUG=None
TEST=Chaps unit tests (with ASAN) plus PKCS11 tests

Change-Id: Ia5fe6101df5ca7861950600119f5ef1f5f66f509
Reviewed-on: https://chromium-review.googlesource.com/221935
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: David Drysdale <drysdale@google.com>
Tested-by: David Drysdale <drysdale@google.com>
diff --git a/chaps/chaps.cc b/chaps/chaps.cc
index c94e03c..60abdf9 100644
--- a/chaps/chaps.cc
+++ b/chaps/chaps.cc
@@ -76,7 +76,7 @@
     memcpy(out_buffer, &output.front(), output.size());
   } else {
     *out_buffer_length = static_cast<CK_ULONG>(output_length);
-    if (result == CKR_BUFFER_TOO_SMALL)
+    if (result == CKR_BUFFER_TOO_SMALL && !out_buffer)
       result = CKR_OK;
   }
   return result;
diff --git a/chaps/chaps_test.cc b/chaps/chaps_test.cc
index b307851..1d1761b 100644
--- a/chaps/chaps_test.cc
+++ b/chaps/chaps_test.cc
@@ -1467,6 +1467,24 @@
             C_DecryptFinal(1, buffer_out_, &length_out_));
 }
 
+TEST_F(TestEncrypt, EncryptSmallBuffer) {
+  ChapsProxyMock proxy(true);
+  EXPECT_CALL(proxy, Encrypt(_, 1, data_in_, 1, _, _)).
+      WillOnce(DoAll(SetArgumentPointee<4>(length_out_expected_),
+                     Return(CKR_BUFFER_TOO_SMALL)));
+  EXPECT_CALL(proxy, Decrypt(_, 1, data_in_, 1, _, _)).
+      WillOnce(DoAll(SetArgumentPointee<4>(length_out_expected_),
+                     Return(CKR_BUFFER_TOO_SMALL)));
+  length_out_ = 1;
+  EXPECT_EQ(CKR_BUFFER_TOO_SMALL,
+            C_Encrypt(1, buffer_in_, length_in_, buffer_out_, &length_out_));
+  EXPECT_EQ(length_out_, length_out_expected_);
+  length_out_ = 1;
+  EXPECT_EQ(CKR_BUFFER_TOO_SMALL,
+            C_Decrypt(1, buffer_in_, length_in_, buffer_out_, &length_out_));
+  EXPECT_EQ(length_out_, length_out_expected_);
+}
+
 TEST_F(TestEncrypt, EncryptLengthOnly) {
   ChapsProxyMock proxy(true);
   EXPECT_CALL(proxy, Encrypt(_, 1, data_in_, 0, _, _)).