2efab77b023b9267285ac05f2fa70669281080e1
[platform/core/test/security-tests.git] / src / e2ee-adaptation-layer / tests.cpp
1 /*
2  *  Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License
15  */
16
17 #include "e2ee-adaptation-layer.h"
18
19 #include <sstream>
20
21 #include <openssl/evp.h>
22 #include <openssl/x509.h>
23 #include <openssl/pem.h>
24 #include <openssl/crypto.h>
25
26 #include <dpl/test/test_runner.h>
27 #include <ckm-common.h>
28 #include <ckmc/ckmc-manager.h>
29 #include <ckmc/ckmc-control.h>
30 #include <device_certificate_manager.h>
31
32 namespace {
33
34 const uid_t UID = 5001;
35
36 struct KeyAliasPair
37 {
38     std::string prv;
39     std::string pub;
40 };
41
42 const KeyAliasPair OURS = { "our_ec_private", "our_ec_public" };
43 const KeyAliasPair PEERS = { "peer_ec_private", "peer_ec_public" };
44 const KeyAliasPair PEERS2 = { "peer2_ec_private", "peer2_ec_public" };
45 const KeyAliasPair WRONG = { "wrong_ec_private", "wrong_ec_public" };
46 const KeyAliasPair RSA_KEYS = { "rsa_private", "rsa_public" };
47
48 const char* const DERIVED = "derived";
49
50 constexpr size_t SALT_LEN = 16;
51 const unsigned char SALT[SALT_LEN] = {};
52
53 const ckmc_policy_s UNEXPORTABLE { nullptr, false };
54 const ckmc_policy_s EXPORTABLE { nullptr, true };
55
56 #define ERRORDESCRIBE(name) case name: return #name
57 const char * E2EEErrorToString(int error) {
58     switch(error) {
59         ERRORDESCRIBE(DCM_ERROR_INVALID_PARAMETER);
60         ERRORDESCRIBE(DCM_ERROR_OUT_OF_MEMORY);
61         ERRORDESCRIBE(DCM_ERROR_PERMISSION_DENIED);
62         ERRORDESCRIBE(DCM_ERROR_NOT_SUPPORTED);
63         ERRORDESCRIBE(DCM_ERROR_NO_DATA);
64         ERRORDESCRIBE(DCM_ERROR_UNKNOWN);
65         ERRORDESCRIBE(DCM_ERROR_SOCKET);
66         ERRORDESCRIBE(DCM_ERROR_MSG_FORMAT);
67         default: return CKMCErrorToString(error);
68     }
69 }
70 #undef ERRORDESCRIBE
71
72 // RUNNER_ASSERT wrappers
73 template <typename F, typename... Args>
74 void e2ee_result(int expected, F&& func, Args... args)
75 {
76     int ret = func(args...);
77     RUNNER_ASSERT_MSG(ret == expected,
78                       "Expected: " << E2EEErrorToString(expected) << "(" << expected << ")"
79                       " got: " << E2EEErrorToString(ret) << "(" << ret << ")");
80 }
81
82 template <typename F, typename... Args>
83 void e2ee_positive(F&& func, Args... args)
84 {
85     e2ee_result(DCM_ERROR_NONE, std::move(func), args...);
86 }
87
88 template <typename F, typename... Args>
89 void e2ee_invalid_param(F&& func, Args... args)
90 {
91     e2ee_result(DCM_ERROR_INVALID_PARAMETER, std::move(func), args...);
92 }
93
94 class EALGroupFixture: public DPL::Test::TestGroup
95 {
96 private:
97     void GenerateEC(ckmc_ec_type_e curve,
98                     const KeyAliasPair& pair,
99                     const ckmc_policy_s& policy_prv,
100                     const ckmc_policy_s& policy_pub)
101     {
102         ckmc_remove_alias(pair.prv.c_str());
103         ckmc_remove_alias(pair.pub.c_str());
104         e2ee_positive(ckmc_create_key_pair_ecdsa,
105                       curve,
106                       pair.prv.c_str(),
107                       pair.pub.c_str(),
108                       policy_prv,
109                       policy_pub);
110     }
111
112 public:
113     void Init() override
114     {
115         remove_user_data(UID);
116         e2ee_positive(ckmc_unlock_user_key, UID, "db-pass");
117
118         GenerateEC(CKMC_EC_PRIME256V1, OURS, UNEXPORTABLE, EXPORTABLE);
119         GenerateEC(CKMC_EC_PRIME256V1, PEERS, UNEXPORTABLE, EXPORTABLE);
120         GenerateEC(CKMC_EC_PRIME256V1, PEERS2, EXPORTABLE, EXPORTABLE);
121         GenerateEC(CKMC_EC_PRIME192V1, WRONG, UNEXPORTABLE, EXPORTABLE);
122
123         ckmc_remove_alias(RSA_KEYS.prv.c_str());
124         ckmc_remove_alias(RSA_KEYS.pub.c_str());
125         e2ee_positive(ckmc_create_key_pair_rsa,
126                       1024,
127                       RSA_KEYS.prv.c_str(),
128                       RSA_KEYS.pub.c_str(),
129                       UNEXPORTABLE,
130                       EXPORTABLE);
131     }
132
133     void Finish() override
134     {
135         int ret = ckmc_lock_user_key(UID);
136         if (ret != CKMC_ERROR_NONE)
137             RUNNER_ERROR_MSG("DB lock failed: " << CKMCErrorToString(ret));
138         remove_user_data(UID);
139     }
140 };
141 typedef std::unique_ptr<ckmc_key_s, decltype(&ckmc_key_free)> KeyPtr;
142
143 KeyPtr getKey(const std::string& alias)
144 {
145     ckmc_key_s* key = nullptr;
146     e2ee_positive(ckmc_get_key, alias.c_str(), "", &key);
147
148     return KeyPtr(key, ckmc_key_free);
149 }
150
151 AliasRemover keyAgreement(const std::string &prv, const std::string& pub, const char* derived)
152 {
153     auto pub_key = getKey(pub);
154     e2ee_positive(ckmew_key_agreement, prv.c_str(), pub_key->raw_key, pub_key->key_size, derived);
155
156     return AliasRemover(derived);
157 }
158
159 template <typename T, void (*Fn)(T*)>
160 struct Free {
161     explicit Free(T* ptr) : ptr(ptr) {}
162     ~Free() {
163         Fn(ptr);
164     }
165     Free(const Free&) = delete;
166     Free& operator=(const Free&) = delete;
167     T* operator*() { return ptr; }
168 private:
169     T* ptr;
170 };
171
172 void OPENSSL_free_wrapper(unsigned char* ptr)
173 {
174     OPENSSL_free(static_cast<void*>(ptr));
175 }
176
177 typedef Free<dcm_e2ee_bundle_s, dcm_e2ee_free_bundle> FreeBundle;
178 typedef Free<void, free> FreeVoid;
179 typedef Free<BIO, BIO_free_all> FreeBio;
180 typedef Free<unsigned char, OPENSSL_free_wrapper> FreeOpenssl;
181 typedef Free<X509, X509_free> FreeX509;
182 typedef Free<EVP_MD_CTX, EVP_MD_CTX_free> FreeMdCtx;
183 typedef Free<X509_STORE_CTX, X509_STORE_CTX_free> FreeX509StoreCtx;
184
185 typedef STACK_OF(X509) X509_STACK;
186 typedef std::unique_ptr<X509_STACK, decltype(&sk_X509_free)> X509StackPtr;
187
188 X509StackPtr getOcfChain()
189 {
190     // extract OCFs root certificate
191     char* ocfChain = nullptr;
192     size_t ocfChainLen = 0;
193
194     // OCF cert + common OCFs root cert
195     e2ee_positive(ckmew_get_ocf_cert_chain, &ocfChain, &ocfChainLen);
196
197     RUNNER_ASSERT_MSG(ocfChain != nullptr, "OCF cert chain is empty");
198
199     FreeVoid ocfChainFree(static_cast<void*>(ocfChain));
200
201     RUNNER_ASSERT_MSG(ocfChainLen > 0, "OCF cert chain has 0 length");
202
203     auto bio = (BIO_new(BIO_s_mem()));
204     RUNNER_ASSERT_MSG(bio != nullptr, "BIO_new failed");
205     FreeBio bioFree(bio);
206
207     auto written = BIO_write(bio, ocfChain, ocfChainLen);
208     RUNNER_ASSERT_MSG(written >= 0, "BIO_write failed");
209     RUNNER_ASSERT_MSG(static_cast<size_t>(written) == ocfChainLen, "OCF chain write is incomplete");
210
211     // build a X509 chain
212     X509StackPtr chainPtr(sk_X509_new_null(), sk_X509_free);
213     RUNNER_ASSERT_MSG(chainPtr, "sk_X509_new_null failed");
214
215     X509* cert = nullptr;
216     while((cert = PEM_read_bio_X509(bio, nullptr, nullptr, nullptr)) != nullptr)
217         RUNNER_ASSERT_MSG(sk_X509_push(chainPtr.get(), cert) > 0, "Nothing was pushed to stack");
218
219     // make sure the chain is long enough
220     RUNNER_ASSERT_MSG(sk_X509_num(chainPtr.get()) >= 2,
221                       "Insufficient number of certificates in the chain");
222
223     return chainPtr;
224 }
225
226 struct ustreambuf: public std::basic_streambuf<unsigned char> {
227     ustreambuf(unsigned char* buf, size_t size) : std::basic_streambuf<unsigned char>()
228     {
229         pubsetbuf(buf, size);
230     }
231 };
232
233 class Peer
234 {
235 public:
236     Peer(const KeyAliasPair& keys, const char* derived) : ours(keys), derived(derived) {}
237     ~Peer() {
238         ckmc_remove_alias(derived);
239     }
240
241     std::string send()
242     {
243         ckmc_raw_buffer_s* message = nullptr;
244         ckmc_raw_buffer_s* signature = nullptr;
245         e2ee_positive(ckmew_sign_with_ocf, ours.pub.c_str(), &message, &signature);
246
247         auto messagePtr = create_raw_buffer(message);
248         auto signaturePtr = create_raw_buffer(signature);
249
250         RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer has 0 length");
251         RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer has no data");
252
253         RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer has 0 length");
254         RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Signature buffer has no data");
255
256         // extract OCF key certificate
257         auto chainPtr = getOcfChain();
258         auto ocfCertX509 = sk_X509_value(chainPtr.get(), 0);
259
260         RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate extraction failed");
261
262         // convert it to DER
263         unsigned char *ocfCert = nullptr;
264         size_t ocfCertLen = i2d_X509(ocfCertX509, &ocfCert);
265
266         RUNNER_ASSERT_MSG(ocfCertLen > 0, "OCF certificate has 0 length");
267         RUNNER_ASSERT_MSG(ocfCert != nullptr, "OCF certificate is empty");
268         FreeOpenssl certFree(ocfCert);
269
270         // serialize
271         std::ostringstream os;
272         auto serialize = [&](const unsigned char* data, size_t size){
273             os.write(reinterpret_cast<const char*>(&size), sizeof(size));
274             os.write(reinterpret_cast<const char*>(data), size);
275         };
276
277         serialize(message->data, message->size);
278         serialize(signature->data, signature->size);
279         serialize(ocfCert, ocfCertLen);
280
281         return os.str();
282     }
283
284     void receive(std::string&& buffer)
285     {
286         // deserialize
287         std::istringstream is(buffer);
288         auto deserialize = [&]()
289         {
290             size_t size;
291             is.read(reinterpret_cast<char*>(&size), sizeof(size));
292             RUNNER_ASSERT_MSG(size > 0, "Deserialized 0 length vector");
293             std::vector<unsigned char> data(size);
294             is.read(reinterpret_cast<char*>(data.data()), size);
295
296             return data;
297         };
298
299         auto message = deserialize();
300         auto signature = deserialize();
301         auto ocfCert = deserialize();
302
303         // decompose message
304         unsigned char* messageDup = static_cast<unsigned char*>(malloc(message.size()));
305         RUNNER_ASSERT_MSG(messageDup != nullptr, "Memory allocation failed");
306         memcpy(messageDup, message.data(), message.size());
307
308         dcm_e2ee_bundle_h bundle = nullptr;
309         e2ee_positive(dcm_e2ee_create_bundle, messageDup, message.size(), &bundle);
310         RUNNER_ASSERT_MSG(bundle != nullptr, "Bundle creation failed");
311         FreeBundle freeBundle(bundle);
312
313         const char* platform = nullptr;
314         e2ee_positive(dcm_e2ee_get_bundle_platform, bundle, &platform);
315         RUNNER_ASSERT_MSG(strcmp(platform, "Tizen") == 0, "Unexpected platform:" << platform);
316
317         char* label = NULL;
318         ssize_t size = smack_new_label_from_self(&label);
319         RUNNER_ASSERT_MSG(size > 0 &&  label != nullptr, "Smack label acquisition failed");
320         FreeVoid freeLabel(static_cast<void*>(label));
321
322         const char* pkgId = nullptr;
323         e2ee_positive(dcm_e2ee_get_bundle_pkg_id, bundle, &pkgId);
324         RUNNER_ASSERT_MSG(strcmp(pkgId, label) == 0, "Unexpected pkg id:" << pkgId);
325
326         const unsigned char* peerPubDevKey = nullptr;
327         size_t peerPubDevKeyLen = 0;
328         e2ee_positive(dcm_e2ee_get_bundle_payload, bundle, &peerPubDevKey, &peerPubDevKeyLen);
329         RUNNER_ASSERT_MSG(peerPubDevKey != nullptr, "Empty public key");
330         RUNNER_ASSERT_MSG(peerPubDevKeyLen > 0, "Public key has zero length");
331
332         // parse OCF certificate
333         const unsigned char* ocfCertPtr = ocfCert.data();
334         auto ocfCertX509 = d2i_X509(nullptr, &ocfCertPtr, ocfCert.size());
335         RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate parsing failed");
336         FreeX509 freeCert(ocfCertX509);
337
338         // extract OCF public key from OCF certificate
339         EVP_PKEY *ocfPubKey = X509_get0_pubkey(ocfCertX509);
340         RUNNER_ASSERT_MSG(ocfPubKey != nullptr, "Can't get public key from OCF certificate");
341
342         // verify OCF signature
343         EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
344         RUNNER_ASSERT_MSG(mdctx != nullptr, "EVP_MD_CTX_new failed");
345         FreeMdCtx freeMd(mdctx);
346
347         int ret = EVP_DigestVerifyInit(mdctx, nullptr, EVP_sha256(), nullptr, ocfPubKey);
348         RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyInit failed");
349
350         ret = EVP_DigestVerifyUpdate(mdctx, message.data(), message.size());
351         RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyUpdate failed");
352
353         ret = EVP_DigestVerifyFinal(mdctx, signature.data(), signature.size());
354         RUNNER_ASSERT_MSG(ret == 1, "OCF signature verification failed");
355
356         // verify received cert with local certchain
357         auto chainPtr = getOcfChain();
358
359         // pop and free the first certificate (OCF)
360         X509_free(sk_X509_shift(chainPtr.get()));
361
362         // pop the last certificate (OCF root)
363         auto ocfRoot = sk_X509_pop(chainPtr.get());
364         RUNNER_ASSERT_MSG(ocfRoot != nullptr, "OCF root cert is NULL");
365         FreeX509 freeOcfRoot(ocfRoot);
366
367         X509_STORE* store = X509_STORE_new();
368         FreeX509StoreCtx storeCtx(X509_STORE_CTX_new());
369
370         // add OCF root as a trusted cert
371         ret = X509_STORE_add_cert(store, ocfRoot);
372         RUNNER_ASSERT_MSG(ret == 1, "Failed to add certificate to the store");
373
374         // store becomes a member of storeCtx
375         ret = X509_STORE_CTX_init(*storeCtx, store, ocfCertX509, chainPtr.get());
376         RUNNER_ASSERT_MSG(ret == 1, "X509_STORE_CTX_init failed");
377         ret = X509_verify_cert(*storeCtx);
378         RUNNER_ASSERT_MSG(ret == 1, "OCF certificate verification failed");
379
380         // derive shared key
381         e2ee_positive(ckmew_key_agreement,
382                       ours.prv.c_str(),
383                       peerPubDevKey,
384                       peerPubDevKeyLen,
385                       derived);
386     }
387
388     RawBufferPtr encrypt(const ParamListPtr& params, const RawBufferPtr& plain)
389     {
390         ckmc_raw_buffer_s* encrypted = nullptr;
391         e2ee_positive(ckmc_encrypt_data, params.get(), derived, "", *plain.get(), &encrypted);
392         return create_raw_buffer(encrypted);
393     }
394
395     RawBufferPtr decrypt(const ParamListPtr& params, const RawBufferPtr& encrypted)
396     {
397         ckmc_raw_buffer_s* decrypted = nullptr;
398         e2ee_positive(ckmc_decrypt_data, params.get(), derived, "", *encrypted.get(), &decrypted);
399         return create_raw_buffer(decrypted);
400     }
401
402 private:
403     const KeyAliasPair& ours;
404     const char* derived;
405 };
406
407 } // namespace anonymous
408
409 RUNNER_TEST_GROUP_INIT_ENV(E2EE_ADAPTATION_LAYER, EALGroupFixture);
410
411 RUNNER_TEST(TEAL_0010_key_agreement_positive)
412 {
413     const char* const OURS_DERIVED = "ours_derived";
414     const char* const PEERS_DERIVED = "peers_derived";
415     const char* const PEERS2_DERIVED = "peers2_derived";
416
417     auto our_remover = keyAgreement(OURS.prv, PEERS.pub, OURS_DERIVED);
418     auto peer_remover = keyAgreement(PEERS.prv, OURS.pub, PEERS_DERIVED);
419     auto peer2_remover = keyAgreement(PEERS2.prv, OURS.pub, PEERS2_DERIVED);
420
421     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
422     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
423
424     auto params = createParamListPtr();
425     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
426     setParam(params, CKMC_PARAM_ED_IV, iv.get());
427
428     ckmc_raw_buffer_s* encrypted = nullptr;
429     e2ee_positive(ckmc_encrypt_data, params.get(), OURS_DERIVED, "", *plain.get(), &encrypted);
430     auto encryptedPtr = create_raw_buffer(encrypted);
431
432     ckmc_raw_buffer_s* decrypted = nullptr;
433     e2ee_positive(ckmc_decrypt_data, params.get(), PEERS_DERIVED, "", *encrypted, &decrypted);
434     auto decryptedPtr = create_raw_buffer(decrypted);
435
436     assert_buffers_equal(plain.get(), decrypted);
437
438     decryptedPtr.reset();
439     decrypted = nullptr;
440     e2ee_positive(ckmc_decrypt_data, params.get(), PEERS2_DERIVED, "", *encrypted, &decrypted);
441     decryptedPtr = create_raw_buffer(decrypted);
442
443     assert_buffers_equal(plain.get(), decrypted, false);
444 }
445
446
447 RUNNER_TEST(TEAL_0020_key_agreement_wrong_arguments)
448 {
449     auto pub_key = getKey(PEERS.pub);
450
451     auto invalid = [](const char* prv,
452                       const unsigned char* pub,
453                       size_t pub_size,
454                       const char* derived)
455     {
456         e2ee_invalid_param(ckmew_key_agreement, prv, pub, pub_size, derived);
457     };
458
459     auto garbage = create_raw_buffer(createRandomBufferCAPI(pub_key->key_size));
460
461     invalid(nullptr,          pub_key->raw_key, pub_key->key_size, DERIVED);
462     invalid(OURS.pub.c_str(), pub_key->raw_key, pub_key->key_size, DERIVED);
463     invalid(OURS.prv.c_str(), nullptr,          pub_key->key_size, DERIVED);
464     invalid(OURS.prv.c_str(), pub_key->raw_key, 6, DERIVED);
465     invalid(OURS.prv.c_str(), garbage->data,    garbage->size,     DERIVED);
466     invalid(OURS.prv.c_str(), pub_key->raw_key, 0,                 DERIVED);
467     invalid(OURS.prv.c_str(), pub_key->raw_key, pub_key->key_size, nullptr);
468 }
469
470 RUNNER_TEST(TEAL_0030_key_agreement_wrong_aliases)
471 {
472     const char* const DERIVED = "derived";
473
474     auto pub_key = getKey(PEERS.pub);
475
476     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
477                 ckmew_key_agreement,
478                 "",
479                 pub_key->raw_key,
480                 pub_key->key_size,
481                 DERIVED);
482
483     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
484                 ckmew_key_agreement,
485                 "nonexistent-alias",
486                 pub_key->raw_key,
487                 pub_key->key_size,
488                 DERIVED);
489
490     e2ee_positive(ckmew_key_agreement,
491                   OURS.prv.c_str(),
492                   pub_key->raw_key,
493                   pub_key->key_size,
494                   DERIVED);
495
496     AliasRemover remover(DERIVED);
497
498     e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
499                 ckmew_key_agreement,
500                 OURS.prv.c_str(),
501                 pub_key->raw_key,
502                 pub_key->key_size,
503                 DERIVED);
504 }
505
506 RUNNER_TEST(TEAL_1000_pbkdf_positive)
507 {
508     constexpr size_t KEY_LEN = 32;
509
510     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
511     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
512     auto salt = create_raw_buffer(createRandomBufferCAPI(SALT_LEN));
513
514     auto params = createParamListPtr();
515     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
516     setParam(params, CKMC_PARAM_ED_IV, iv.get());
517
518     e2ee_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED);
519     auto remover1 = AliasRemover(DERIVED);
520
521     ckmc_raw_buffer_s* encrypted = nullptr;
522     e2ee_positive(ckmc_encrypt_data, params.get(), DERIVED, "", *plain.get(), &encrypted);
523     auto encryptedPtr = create_raw_buffer(encrypted);
524
525     auto deriveAndDecrypt = [&encryptedPtr, &params](const char* password,
526                                                      const unsigned char* salt,
527                                                      size_t salt_len,
528                                                      size_t key_len)
529     {
530         const char* const DERIVED2 = "derived2";
531         e2ee_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2);
532         auto remover = AliasRemover(DERIVED2);
533
534         ckmc_raw_buffer_s* decrypted = nullptr;
535         e2ee_positive(ckmc_decrypt_data,
536                       params.get(),
537                       DERIVED2,
538                       "",
539                       *encryptedPtr.get(),
540                       &decrypted);
541
542         return create_raw_buffer(decrypted);
543     };
544
545     RawBufferPtr decrypted;
546     decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN);
547     assert_buffers_equal(plain.get(), decrypted.get());
548
549     decrypted = deriveAndDecrypt("wrong", salt->data, salt->size, KEY_LEN);
550     assert_buffers_equal(plain.get(), decrypted.get(), false);
551
552     decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN - 8);
553     assert_buffers_equal(plain.get(), decrypted.get(), false);
554
555     decrypted = deriveAndDecrypt("password", salt->data, salt->size - 1, KEY_LEN);
556     assert_buffers_equal(plain.get(), decrypted.get(), false);
557
558     decrypted = deriveAndDecrypt("password", plain->data, salt->size, KEY_LEN);
559     assert_buffers_equal(plain.get(), decrypted.get(), false);
560 }
561
562 RUNNER_TEST(TEAL_1010_pbkdf_invalid_arguments)
563 {
564     e2ee_invalid_param(ckmew_key_derive_pbkdf2, nullptr,    SALT,    SALT_LEN, 32, DERIVED);
565     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", nullptr, SALT_LEN, 32, DERIVED);
566     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT,    SALT_LEN, 32, nullptr);
567     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT,    SALT_LEN, 0,  DERIVED);
568
569     auto invalidFormat = [&](size_t key_len) {
570         e2ee_result(CKMC_ERROR_INVALID_FORMAT,
571                     ckmew_key_derive_pbkdf2,
572                     "password",
573                     SALT,
574                     SALT_LEN,
575                     key_len,
576                     DERIVED);
577     };
578     invalidFormat(64);
579     invalidFormat(31);
580     invalidFormat(8);
581     invalidFormat(1);
582 }
583
584 RUNNER_TEST(TEAL_1020_pbkdf_wrong_alias)
585 {
586     e2ee_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED);
587
588     auto remover = AliasRemover(DERIVED);
589
590     e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
591                 ckmew_key_derive_pbkdf2,
592                 "password",
593                 SALT,
594                 SALT_LEN,
595                 32,
596                 DERIVED);
597 }
598
599 RUNNER_TEST(TEAL_2000_ocf_positive)
600 {
601     ckmc_raw_buffer_s* message = nullptr;
602     ckmc_raw_buffer_s* signature = nullptr;
603     e2ee_positive(ckmew_sign_with_ocf, OURS.pub.c_str(), &message, &signature);
604
605     auto messagePtr = create_raw_buffer(message);
606     auto signaturePtr = create_raw_buffer(signature);
607
608     RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer size is 0");
609     RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer is empty");
610
611     RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer size is 0");
612     RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Singature buffer is empty");
613 }
614
615 RUNNER_TEST(TEAL_2010_ocf_invalid_param)
616 {
617     ckmc_raw_buffer_s* message = nullptr;
618     ckmc_raw_buffer_s* signature = nullptr;
619
620     auto invalid = [](const char* pub_alias,
621                       ckmc_raw_buffer_s** message,
622                       ckmc_raw_buffer_s** signature)
623     {
624         e2ee_result(DCM_ERROR_INVALID_PARAMETER,
625                     ckmew_sign_with_ocf,
626                     pub_alias,
627                     message,
628                     signature);
629     };
630
631     invalid(nullptr, &message, &signature);
632     invalid(OURS.pub.c_str(), nullptr, &signature);
633     invalid(OURS.pub.c_str(), &message, nullptr);
634 }
635
636 RUNNER_TEST(TEAL_2020_ocf_wrong_public_key)
637 {
638     ckmc_raw_buffer_s* message = nullptr;
639     ckmc_raw_buffer_s* signature = nullptr;
640
641     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
642                 ckmew_sign_with_ocf,
643                 "nonexistent-alias",
644                 &message,
645                 &signature);
646
647     e2ee_result(CKMC_ERROR_NOT_EXPORTABLE,
648                 ckmew_sign_with_ocf,
649                 OURS.prv.c_str(),
650                 &message,
651                 &signature);
652 }
653
654 RUNNER_TEST(TEAL_3000_link_key_agreement_scenario)
655 {
656     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
657     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
658
659     auto params = createParamListPtr();
660     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
661     setParam(params, CKMC_PARAM_ED_IV, iv.get());
662
663     Peer p1(OURS, "our_link_key");
664     Peer p2(PEERS, "peers_link_key");
665
666     p2.receive(p1.send());
667     p1.receive(p2.send());
668
669     auto encrypted = p1.encrypt(params, plain);
670     auto decrypted = p2.decrypt(params, encrypted);
671
672     assert_buffers_equal(plain.get(), decrypted.get());
673 }
674
675 int main(int argc, char *argv[])
676 {
677     require_default_user(argv);
678
679     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
680 }