Enable 2-element OCF certificate chain tests
[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     // make sure the chain is long enough
219     RUNNER_ASSERT_MSG(sk_X509_num(chainPtr.get()) >= 2,
220                       "Insufficient number of certificates in the chain");
221
222     return chainPtr;
223 }
224
225 struct ustreambuf: public std::basic_streambuf<unsigned char> {
226     ustreambuf(unsigned char* buf, size_t size) : std::basic_streambuf<unsigned char>()
227     {
228         pubsetbuf(buf, size);
229     }
230 };
231
232 class Peer
233 {
234 public:
235     Peer(const KeyAliasPair& keys, const char* derived) : ours(keys), derived(derived) {}
236     ~Peer() {
237         ckmc_remove_alias(derived);
238     }
239
240     std::string send()
241     {
242         ckmc_raw_buffer_s* message = nullptr;
243         ckmc_raw_buffer_s* signature = nullptr;
244         e2ee_positive(ckmew_sign_with_ocf, ours.pub.c_str(), &message, &signature);
245
246         auto messagePtr = create_raw_buffer(message);
247         auto signaturePtr = create_raw_buffer(signature);
248
249         RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer has 0 length");
250         RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer has no data");
251
252         RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer has 0 length");
253         RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Signature buffer has no data");
254
255         // extract OCF key certificate
256         auto chainPtr = getOcfChain();
257         auto ocfCertX509 = sk_X509_value(chainPtr.get(), 0);
258
259         RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate extraction failed");
260
261         // convert it to DER
262         unsigned char *ocfCert = nullptr;
263         size_t ocfCertLen = i2d_X509(ocfCertX509, &ocfCert);
264
265         RUNNER_ASSERT_MSG(ocfCertLen > 0, "OCF certificate has 0 length");
266         RUNNER_ASSERT_MSG(ocfCert != nullptr, "OCF certificate is empty");
267         FreeOpenssl certFree(ocfCert);
268
269         // serialize
270         std::ostringstream os;
271         auto serialize = [&](const unsigned char* data, size_t size){
272             os.write(reinterpret_cast<const char*>(&size), sizeof(size));
273             os.write(reinterpret_cast<const char*>(data), size);
274         };
275
276         serialize(message->data, message->size);
277         serialize(signature->data, signature->size);
278         serialize(ocfCert, ocfCertLen);
279
280         return os.str();
281     }
282
283     void receive(std::string&& buffer)
284     {
285         // deserialize
286         std::istringstream is(buffer);
287         auto deserialize = [&]()
288         {
289             size_t size;
290             is.read(reinterpret_cast<char*>(&size), sizeof(size));
291             RUNNER_ASSERT_MSG(size > 0, "Deserialized 0 length vector");
292             std::vector<unsigned char> data(size);
293             is.read(reinterpret_cast<char*>(data.data()), size);
294
295             return data;
296         };
297
298         auto message = deserialize();
299         auto signature = deserialize();
300         auto ocfCert = deserialize();
301
302         // decompose message
303         unsigned char* messageDup = static_cast<unsigned char*>(malloc(message.size()));
304         RUNNER_ASSERT_MSG(messageDup != nullptr, "Memory allocation failed");
305         memcpy(messageDup, message.data(), message.size());
306
307         dcm_e2ee_bundle_h bundle = nullptr;
308         e2ee_positive(dcm_e2ee_create_bundle, messageDup, message.size(), &bundle);
309         RUNNER_ASSERT_MSG(bundle != nullptr, "Bundle creation failed");
310         FreeBundle freeBundle(bundle);
311
312         const char* platform = nullptr;
313         e2ee_positive(dcm_e2ee_get_bundle_platform, bundle, &platform);
314         RUNNER_ASSERT_MSG(strcmp(platform, "Tizen") == 0, "Unexpected platform:" << platform);
315
316         char* label = NULL;
317         ssize_t size = smack_new_label_from_self(&label);
318         RUNNER_ASSERT_MSG(size > 0 &&  label != nullptr, "Smack label acquisition failed");
319         FreeVoid freeLabel(static_cast<void*>(label));
320
321         const char* pkgId = nullptr;
322         e2ee_positive(dcm_e2ee_get_bundle_pkg_id, bundle, &pkgId);
323         RUNNER_ASSERT_MSG(strcmp(pkgId, label) == 0, "Unexpected pkg id:" << pkgId);
324
325         const unsigned char* peerPubDevKey = nullptr;
326         size_t peerPubDevKeyLen = 0;
327         e2ee_positive(dcm_e2ee_get_bundle_payload, bundle, &peerPubDevKey, &peerPubDevKeyLen);
328         RUNNER_ASSERT_MSG(peerPubDevKey != nullptr, "Empty public key");
329         RUNNER_ASSERT_MSG(peerPubDevKeyLen > 0, "Public key has zero length");
330
331         // parse OCF certificate
332         const unsigned char* ocfCertPtr = ocfCert.data();
333         auto ocfCertX509 = d2i_X509(nullptr, &ocfCertPtr, ocfCert.size());
334         RUNNER_ASSERT_MSG(ocfCertX509 != nullptr, "OCF certificate parsing failed");
335         FreeX509 freeCert(ocfCertX509);
336
337         // extract OCF public key from OCF certificate
338         EVP_PKEY *ocfPubKey = X509_get0_pubkey(ocfCertX509);
339         RUNNER_ASSERT_MSG(ocfPubKey != nullptr, "Can't get public key from OCF certificate");
340
341         // verify OCF signature
342         EVP_MD_CTX *mdctx = EVP_MD_CTX_new();
343         RUNNER_ASSERT_MSG(mdctx != nullptr, "EVP_MD_CTX_new failed");
344         FreeMdCtx freeMd(mdctx);
345
346         int ret = EVP_DigestVerifyInit(mdctx, nullptr, EVP_sha256(), nullptr, ocfPubKey);
347         RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyInit failed");
348
349         ret = EVP_DigestVerifyUpdate(mdctx, message.data(), message.size());
350         RUNNER_ASSERT_MSG(ret == 1, "EVP_DigestVerifyUpdate failed");
351
352         ret = EVP_DigestVerifyFinal(mdctx, signature.data(), signature.size());
353         RUNNER_ASSERT_MSG(ret == 1, "OCF signature verification failed");
354
355         // verify received cert with local certchain
356         auto chainPtr = getOcfChain();
357
358         // pop and free the first certificate (OCF)
359         X509_free(sk_X509_shift(chainPtr.get()));
360
361         // pop the last certificate (OCF root)
362         auto ocfRoot = sk_X509_pop(chainPtr.get());
363         RUNNER_ASSERT_MSG(ocfRoot != nullptr, "OCF root cert is NULL");
364         FreeX509 freeOcfRoot(ocfRoot);
365
366         X509_STORE* store = X509_STORE_new();
367         FreeX509StoreCtx storeCtx(X509_STORE_CTX_new());
368
369         // add OCF root as a trusted cert
370         ret = X509_STORE_add_cert(store, ocfRoot);
371         RUNNER_ASSERT_MSG(ret == 1, "Failed to add certificate to the store");
372
373         // store becomes a member of storeCtx
374         ret = X509_STORE_CTX_init(*storeCtx, store, ocfCertX509, chainPtr.get());
375         RUNNER_ASSERT_MSG(ret == 1, "X509_STORE_CTX_init failed");
376         ret = X509_verify_cert(*storeCtx);
377         RUNNER_ASSERT_MSG(ret == 1, "OCF certificate verification failed");
378
379         // derive shared key
380         e2ee_positive(ckmew_key_agreement,
381                       ours.prv.c_str(),
382                       peerPubDevKey,
383                       peerPubDevKeyLen,
384                       derived);
385     }
386
387     RawBufferPtr encrypt(const ParamListPtr& params, const RawBufferPtr& plain)
388     {
389         ckmc_raw_buffer_s* encrypted = nullptr;
390         e2ee_positive(ckmc_encrypt_data, params.get(), derived, "", *plain.get(), &encrypted);
391         return create_raw_buffer(encrypted);
392     }
393
394     RawBufferPtr decrypt(const ParamListPtr& params, const RawBufferPtr& encrypted)
395     {
396         ckmc_raw_buffer_s* decrypted = nullptr;
397         e2ee_positive(ckmc_decrypt_data, params.get(), derived, "", *encrypted.get(), &decrypted);
398         return create_raw_buffer(decrypted);
399     }
400
401 private:
402     const KeyAliasPair& ours;
403     const char* derived;
404 };
405
406 } // namespace anonymous
407
408 RUNNER_TEST_GROUP_INIT_ENV(E2EE_ADAPTATION_LAYER, EALGroupFixture);
409
410 RUNNER_TEST(TEAL_0010_key_agreement_positive)
411 {
412     const char* const OURS_DERIVED = "ours_derived";
413     const char* const PEERS_DERIVED = "peers_derived";
414     const char* const PEERS2_DERIVED = "peers2_derived";
415
416     auto our_remover = keyAgreement(OURS.prv, PEERS.pub, OURS_DERIVED);
417     auto peer_remover = keyAgreement(PEERS.prv, OURS.pub, PEERS_DERIVED);
418     auto peer2_remover = keyAgreement(PEERS2.prv, OURS.pub, PEERS2_DERIVED);
419
420     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
421     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
422
423     auto params = createParamListPtr();
424     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
425     setParam(params, CKMC_PARAM_ED_IV, iv.get());
426
427     ckmc_raw_buffer_s* encrypted = nullptr;
428     e2ee_positive(ckmc_encrypt_data, params.get(), OURS_DERIVED, "", *plain.get(), &encrypted);
429     auto encryptedPtr = create_raw_buffer(encrypted);
430
431     ckmc_raw_buffer_s* decrypted = nullptr;
432     e2ee_positive(ckmc_decrypt_data, params.get(), PEERS_DERIVED, "", *encrypted, &decrypted);
433     auto decryptedPtr = create_raw_buffer(decrypted);
434
435     assert_buffers_equal(plain.get(), decrypted);
436
437     decryptedPtr.reset();
438     decrypted = nullptr;
439     e2ee_positive(ckmc_decrypt_data, params.get(), PEERS2_DERIVED, "", *encrypted, &decrypted);
440     decryptedPtr = create_raw_buffer(decrypted);
441
442     assert_buffers_equal(plain.get(), decrypted, false);
443 }
444
445
446 RUNNER_TEST(TEAL_0020_key_agreement_wrong_arguments)
447 {
448     auto pub_key = getKey(PEERS.pub);
449
450     auto invalid = [](const char* prv,
451                       const unsigned char* pub,
452                       size_t pub_size,
453                       const char* derived)
454     {
455         e2ee_invalid_param(ckmew_key_agreement, prv, pub, pub_size, derived);
456     };
457
458     auto garbage = create_raw_buffer(createRandomBufferCAPI(pub_key->key_size));
459
460     invalid(nullptr,          pub_key->raw_key, pub_key->key_size, DERIVED);
461     invalid(OURS.pub.c_str(), pub_key->raw_key, pub_key->key_size, DERIVED);
462     invalid(OURS.prv.c_str(), nullptr,          pub_key->key_size, DERIVED);
463     invalid(OURS.prv.c_str(), pub_key->raw_key, 6, DERIVED);
464     invalid(OURS.prv.c_str(), garbage->data,    garbage->size,     DERIVED);
465     invalid(OURS.prv.c_str(), pub_key->raw_key, 0,                 DERIVED);
466     invalid(OURS.prv.c_str(), pub_key->raw_key, pub_key->key_size, nullptr);
467 }
468
469 RUNNER_TEST(TEAL_0030_key_agreement_wrong_aliases)
470 {
471     const char* const DERIVED = "derived";
472
473     auto pub_key = getKey(PEERS.pub);
474
475     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
476                 ckmew_key_agreement,
477                 "",
478                 pub_key->raw_key,
479                 pub_key->key_size,
480                 DERIVED);
481
482     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
483                 ckmew_key_agreement,
484                 "nonexistent-alias",
485                 pub_key->raw_key,
486                 pub_key->key_size,
487                 DERIVED);
488
489     e2ee_positive(ckmew_key_agreement,
490                   OURS.prv.c_str(),
491                   pub_key->raw_key,
492                   pub_key->key_size,
493                   DERIVED);
494
495     AliasRemover remover(DERIVED);
496
497     e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
498                 ckmew_key_agreement,
499                 OURS.prv.c_str(),
500                 pub_key->raw_key,
501                 pub_key->key_size,
502                 DERIVED);
503 }
504
505 RUNNER_TEST(TEAL_1000_pbkdf_positive)
506 {
507     constexpr size_t KEY_LEN = 32;
508
509     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
510     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
511     auto salt = create_raw_buffer(createRandomBufferCAPI(SALT_LEN));
512
513     auto params = createParamListPtr();
514     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
515     setParam(params, CKMC_PARAM_ED_IV, iv.get());
516
517     e2ee_positive(ckmew_key_derive_pbkdf2, "password", salt->data, salt->size, KEY_LEN, DERIVED);
518     auto remover1 = AliasRemover(DERIVED);
519
520     ckmc_raw_buffer_s* encrypted = nullptr;
521     e2ee_positive(ckmc_encrypt_data, params.get(), DERIVED, "", *plain.get(), &encrypted);
522     auto encryptedPtr = create_raw_buffer(encrypted);
523
524     auto deriveAndDecrypt = [&encryptedPtr, &params](const char* password,
525                                                      const unsigned char* salt,
526                                                      size_t salt_len,
527                                                      size_t key_len)
528     {
529         const char* const DERIVED2 = "derived2";
530         e2ee_positive(ckmew_key_derive_pbkdf2, password, salt, salt_len, key_len, DERIVED2);
531         auto remover = AliasRemover(DERIVED2);
532
533         ckmc_raw_buffer_s* decrypted = nullptr;
534         e2ee_positive(ckmc_decrypt_data,
535                       params.get(),
536                       DERIVED2,
537                       "",
538                       *encryptedPtr.get(),
539                       &decrypted);
540
541         return create_raw_buffer(decrypted);
542     };
543
544     RawBufferPtr decrypted;
545     decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN);
546     assert_buffers_equal(plain.get(), decrypted.get());
547
548     decrypted = deriveAndDecrypt("wrong", salt->data, salt->size, KEY_LEN);
549     assert_buffers_equal(plain.get(), decrypted.get(), false);
550
551     decrypted = deriveAndDecrypt("password", salt->data, salt->size, KEY_LEN - 8);
552     assert_buffers_equal(plain.get(), decrypted.get(), false);
553
554     decrypted = deriveAndDecrypt("password", salt->data, salt->size - 1, KEY_LEN);
555     assert_buffers_equal(plain.get(), decrypted.get(), false);
556
557     decrypted = deriveAndDecrypt("password", plain->data, salt->size, KEY_LEN);
558     assert_buffers_equal(plain.get(), decrypted.get(), false);
559 }
560
561 RUNNER_TEST(TEAL_1010_pbkdf_invalid_arguments)
562 {
563     e2ee_invalid_param(ckmew_key_derive_pbkdf2, nullptr,    SALT,    SALT_LEN, 32, DERIVED);
564     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", nullptr, SALT_LEN, 32, DERIVED);
565     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT,    SALT_LEN, 32, nullptr);
566     e2ee_invalid_param(ckmew_key_derive_pbkdf2, "password", SALT,    SALT_LEN, 0,  DERIVED);
567
568     auto invalidFormat = [&](size_t key_len) {
569         e2ee_result(CKMC_ERROR_INVALID_FORMAT,
570                     ckmew_key_derive_pbkdf2,
571                     "password",
572                     SALT,
573                     SALT_LEN,
574                     key_len,
575                     DERIVED);
576     };
577     invalidFormat(64);
578     invalidFormat(31);
579     invalidFormat(8);
580     invalidFormat(1);
581 }
582
583 RUNNER_TEST(TEAL_1020_pbkdf_wrong_alias)
584 {
585     e2ee_positive(ckmew_key_derive_pbkdf2, "password", SALT, SALT_LEN, 32, DERIVED);
586
587     auto remover = AliasRemover(DERIVED);
588
589     e2ee_result(CKMC_ERROR_DB_ALIAS_EXISTS,
590                 ckmew_key_derive_pbkdf2,
591                 "password",
592                 SALT,
593                 SALT_LEN,
594                 32,
595                 DERIVED);
596 }
597
598 RUNNER_TEST(TEAL_2000_ocf_positive)
599 {
600     ckmc_raw_buffer_s* message = nullptr;
601     ckmc_raw_buffer_s* signature = nullptr;
602     e2ee_positive(ckmew_sign_with_ocf, OURS.pub.c_str(), &message, &signature);
603
604     auto messagePtr = create_raw_buffer(message);
605     auto signaturePtr = create_raw_buffer(signature);
606
607     RUNNER_ASSERT_MSG(messagePtr->size > 0, "Message buffer size is 0");
608     RUNNER_ASSERT_MSG(messagePtr->data != nullptr, "Message buffer is empty");
609
610     RUNNER_ASSERT_MSG(signaturePtr->size > 0, "Signature buffer size is 0");
611     RUNNER_ASSERT_MSG(signaturePtr->data != nullptr, "Singature buffer is empty");
612 }
613
614 RUNNER_TEST(TEAL_2010_ocf_invalid_param)
615 {
616     ckmc_raw_buffer_s* message = nullptr;
617     ckmc_raw_buffer_s* signature = nullptr;
618
619     auto invalid = [](const char* pub_alias,
620                       ckmc_raw_buffer_s** message,
621                       ckmc_raw_buffer_s** signature)
622     {
623         e2ee_result(DCM_ERROR_INVALID_PARAMETER,
624                     ckmew_sign_with_ocf,
625                     pub_alias,
626                     message,
627                     signature);
628     };
629
630     invalid(nullptr, &message, &signature);
631     invalid(OURS.pub.c_str(), nullptr, &signature);
632     invalid(OURS.pub.c_str(), &message, nullptr);
633 }
634
635 RUNNER_TEST(TEAL_2020_ocf_wrong_public_key)
636 {
637     ckmc_raw_buffer_s* message = nullptr;
638     ckmc_raw_buffer_s* signature = nullptr;
639
640     e2ee_result(CKMC_ERROR_DB_ALIAS_UNKNOWN,
641                 ckmew_sign_with_ocf,
642                 "nonexistent-alias",
643                 &message,
644                 &signature);
645
646     e2ee_result(CKMC_ERROR_NOT_EXPORTABLE,
647                 ckmew_sign_with_ocf,
648                 OURS.prv.c_str(),
649                 &message,
650                 &signature);
651 }
652
653 RUNNER_TEST(TEAL_3000_link_key_agreement_scenario)
654 {
655     auto plain = create_raw_buffer(createRandomBufferCAPI(512));
656     auto iv = create_raw_buffer(createRandomBufferCAPI(16));
657
658     auto params = createParamListPtr();
659     setParam(params, CKMC_PARAM_ALGO_TYPE, CKMC_ALGO_AES_CTR);
660     setParam(params, CKMC_PARAM_ED_IV, iv.get());
661
662     Peer p1(OURS, "our_link_key");
663     Peer p2(PEERS, "peers_link_key");
664
665     p2.receive(p1.send());
666     p1.receive(p2.send());
667
668     auto encrypted = p1.encrypt(params, plain);
669     auto decrypted = p2.decrypt(params, encrypted);
670
671     assert_buffers_equal(plain.get(), decrypted.get());
672 }
673
674 int main(int argc, char *argv[])
675 {
676     require_default_user(argv);
677
678     return DPL::Test::TestRunnerSingleton::Instance().ExecTestRunner(argc, argv);
679 }