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