themis_secure_message_signer_t* themis_secure_message_signer_init(const uint8_t* key, const size_t key_length) { themis_secure_message_signer_t* ctx=malloc(sizeof(themis_secure_message_signer_t)); if(!ctx){ return NULL; } ctx->sign_ctx=NULL; ctx->sign_ctx=soter_sign_create(get_alg_id(key,key_length),NULL,0,key, key_length); if(!(ctx->sign_ctx)){ free(ctx); return NULL; } return ctx; }
themis_status_t themis_gen_key_pair(soter_sign_alg_t alg, uint8_t* private_key, size_t* private_key_length, uint8_t* public_key, size_t* public_key_length) { soter_sign_ctx_t* ctx=soter_sign_create(alg,NULL,0,NULL,0); THEMIS_CHECK(ctx!=NULL); soter_status_t res=soter_sign_export_key(ctx, private_key, private_key_length, true); if(res!=THEMIS_SUCCESS && res != THEMIS_BUFFER_TOO_SMALL){ soter_sign_destroy(ctx); return res; } soter_status_t res2=soter_sign_export_key(ctx, public_key, public_key_length, false); if(res2!=THEMIS_SUCCESS && res2!=THEMIS_BUFFER_TOO_SMALL){ soter_sign_destroy(ctx); return res; } soter_sign_destroy(ctx); if(res==THEMIS_BUFFER_TOO_SMALL || res2==THEMIS_BUFFER_TOO_SMALL){ return THEMIS_BUFFER_TOO_SMALL; } return THEMIS_SUCCESS; }
static int sign_test(soter_sign_alg_t alg) { char test_data[]="test message"; size_t test_data_length=strlen(test_data); soter_sign_ctx_t* ctx=NULL; uint8_t* signature=NULL; size_t signature_length=0; ctx=soter_sign_create(alg,NULL,0,NULL,0); if(!ctx){ testsuite_fail_if(!ctx, "soter_sign_ctx_t == NULL"); return -1; } uint8_t private_key[8192]; size_t private_key_length=sizeof(private_key); uint8_t public_key[8192]; size_t public_key_length=sizeof(public_key); soter_status_t res; res=soter_sign_export_key(ctx, private_key, &private_key_length, true); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS,"soter_sign_export_key (private key) fail"); soter_sign_destroy(ctx); return -6; } res=soter_sign_export_key(ctx, public_key, &public_key_length, false); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS,"soter_sign_export_key (public key) fail"); soter_sign_destroy(ctx); return -7; } res=soter_sign_destroy(ctx); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS,"soter_sign_destroy fail"); return -8; } soter_sign_ctx_t* sctx=NULL; sctx=soter_sign_create(alg,private_key,private_key_length,NULL,0); if(!sctx){ testsuite_fail_if(!sctx, "soter_sign_ctx_t == NULL 2"); return -1; } res=soter_sign_update(sctx, test_data, test_data_length); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS, "soter_sign_update fail"); soter_sign_destroy(sctx); return -2; } res=soter_sign_final(sctx, signature, &signature_length); if(res!=SOTER_BUFFER_TOO_SMALL){ testsuite_fail_if(res!=SOTER_BUFFER_TOO_SMALL, "soter_sign_final (signature length determine) fail"); soter_sign_destroy(sctx); return -3; } signature=malloc(signature_length); if(!signature){ testsuite_fail_if(!signature, "out of memory"); soter_sign_destroy(ctx); return -4; } res=soter_sign_final(sctx, signature, &signature_length); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS, "soter_sign_final fail"); soter_sign_destroy(sctx); return -5; } res=soter_sign_destroy(sctx); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS,"soter_sign_destroy fail"); return -8; } soter_verify_ctx_t* vctx=NULL; vctx=soter_verify_create(alg, NULL, 0, public_key, public_key_length); if(!vctx){ testsuite_fail_if(!vctx, "soter_verify_ctx_t == NULL"); return -9; } res=soter_verify_update(vctx, test_data, test_data_length); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS, "soter_verify_update fail"); soter_verify_destroy(vctx); return -10; } res=soter_verify_final(vctx, signature, signature_length); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS, "soter_verify_final fail"); soter_verify_destroy(vctx); return -11; } res=soter_sign_destroy(vctx); if(res!=SOTER_SUCCESS){ testsuite_fail_if(res!=SOTER_SUCCESS,"soter_sign_destroy fail"); return -12; } return 0; }
static void soter_sign_api_test() { uint8_t priv[MAX_TEST_KEY]; size_t priv_length = sizeof(priv); uint8_t pub[MAX_TEST_KEY]; size_t pub_length = sizeof(pub); uint8_t message[MAX_TEST_DATA]; size_t message_length = rand_int(MAX_TEST_DATA); uint8_t signature[MAX_TEST_DATA]; size_t signature_length = sizeof(signature); soter_status_t res; if (soter_rand(message, message_length)) { testsuite_fail_if(true, "soter_rand failed"); return; } soter_sign_ctx_t *sign_ctx = soter_sign_create(SOTER_SIGN_ecdsa_none_pkcs8, NULL, 0, NULL, 0); if (!sign_ctx) { testsuite_fail_if(true, "soter_sign_create failed"); return; } res = soter_sign_export_key(sign_ctx, priv, &priv_length, true); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_sign_export_key failed"); soter_sign_destroy(sign_ctx); return; } res = soter_sign_export_key(sign_ctx, pub, &pub_length, false); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_sign_export_key failed"); soter_sign_destroy(sign_ctx); return; } soter_sign_destroy(sign_ctx); sign_ctx = soter_sign_create((soter_sign_alg_t)-1, priv, priv_length, NULL, 0); testsuite_fail_if(sign_ctx, "soter_sign_create: invalid algorithm"); sign_ctx = soter_sign_create(SOTER_SIGN_ecdsa_none_pkcs8, priv, priv_length - 1, NULL, 0); testsuite_fail_if(sign_ctx, "soter_sign_create: invalid private key length"); sign_ctx = soter_sign_create(SOTER_SIGN_ecdsa_none_pkcs8, priv, priv_length, NULL, 0); if (!sign_ctx) { testsuite_fail_if(true, "soter_sign_create failed"); return; } testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_sign_update(NULL, message, message_length), "soter_sign_update: invalid context"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_sign_update(sign_ctx, NULL, message_length), "soter_sign_update: invalid message"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_sign_update(sign_ctx, message, 0), "soter_sign_update: invalid message length"); res = soter_sign_update(sign_ctx, message, message_length); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_sign_update failed"); soter_sign_destroy(sign_ctx); return; } testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_sign_final(NULL, signature, &signature_length), "soter_sign_final: invalid context"); testsuite_fail_unless(SOTER_BUFFER_TOO_SMALL == soter_sign_final(sign_ctx, NULL, &signature_length), "soter_sign_final: get output size (NULL out buffer)"); signature_length--; testsuite_fail_unless(SOTER_BUFFER_TOO_SMALL == soter_sign_final(sign_ctx, signature, &signature_length), "soter_sign_final: get output size (small out buffer)"); res = soter_sign_final(sign_ctx, signature, &signature_length); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_sign_final failed"); soter_sign_destroy(sign_ctx); return; } testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_sign_destroy(NULL), "soter_sign_destroy: invalid context"); res = soter_sign_destroy(sign_ctx); if (SOTER_SUCCESS != res){ testsuite_fail_if(true, "soter_sign_destroy failed"); return; } sign_ctx = soter_verify_create((soter_sign_alg_t)-1, NULL, 0, pub, pub_length); testsuite_fail_if(sign_ctx, "soter_verify_create: invalid algorithm"); sign_ctx = soter_verify_create(SOTER_SIGN_ecdsa_none_pkcs8, NULL, 0, pub, pub_length - 1); testsuite_fail_if(sign_ctx, "soter_verify_create: invalid public key length"); sign_ctx = soter_verify_create(SOTER_SIGN_ecdsa_none_pkcs8, NULL, 0, pub, pub_length); if (!sign_ctx) { testsuite_fail_if(true, "soter_verify_create failed"); return; } testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_update(NULL, message, message_length), "soter_verify_update: invalid context"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_update(sign_ctx, NULL, message_length), "soter_verify_update: invalid message"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_update(sign_ctx, message, 0), "soter_verify_update: invalid message length"); res = soter_verify_update(sign_ctx, message, message_length); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_verify_update failed"); soter_verify_destroy(sign_ctx); return; } testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_final(NULL, signature, signature_length), "soter_verify_final: invalid context"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_final(sign_ctx, NULL, signature_length), "soter_verify_final: invalid signature buffer"); testsuite_fail_unless(SOTER_INVALID_SIGNATURE == soter_verify_final(sign_ctx, signature, signature_length - 1), "soter_verify_final: invalid signature length"); signature[signature_length / 2]++; testsuite_fail_unless(SOTER_INVALID_SIGNATURE == soter_verify_final(sign_ctx, signature, signature_length), "soter_verify_final: invalid signature value"); signature[signature_length / 2]--; testsuite_fail_unless(SOTER_SUCCESS == soter_verify_final(sign_ctx, signature, signature_length), "soter_verify_final: normal flow"); testsuite_fail_unless(SOTER_INVALID_PARAMETER == soter_verify_destroy(NULL), "soter_verify_destroy: invalid context"); res = soter_verify_destroy(sign_ctx); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_verify_destroy failed"); return; } sign_ctx = soter_verify_create(SOTER_SIGN_ecdsa_none_pkcs8, NULL, 0, pub, pub_length); if (!sign_ctx) { testsuite_fail_if(true, "soter_verify_create failed"); return; } message[message_length / 2]++; res = soter_verify_update(sign_ctx, message, message_length); if (SOTER_SUCCESS != res) { testsuite_fail_if(true, "soter_verify_update failed"); soter_verify_destroy(sign_ctx); return; } message[message_length / 2]--; testsuite_fail_unless(SOTER_INVALID_SIGNATURE == soter_verify_final(sign_ctx, signature, signature_length), "soter_verify_final: wrong signed message"); soter_verify_destroy(sign_ctx); }