// Copyright (c) 2016-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ #include "asn/Condition.h" #include "asn/Fulfillment.h" #include "asn/Ed25519FingerprintContents.h" #include "asn/OCTET_STRING.h" #include "include/cJSON.h" #include "include/ed25519/src/ed25519.h" #include "cryptoconditions.h" struct CCType CC_Ed25519Type; static void ed25519Fingerprint(const CC *cond, uint8_t *out) { Ed25519FingerprintContents_t *fp = calloc(1, sizeof(Ed25519FingerprintContents_t)); OCTET_STRING_fromBuf(&fp->publicKey, cond->publicKey, 32); hashFingerprintContents(&asn_DEF_Ed25519FingerprintContents, fp, out); } int ed25519Verify(CC *cond, CCVisitor visitor) { if (cond->type->typeId != CC_Ed25519Type.typeId) return 1; // TODO: test failure mode: empty sig / null pointer return ed25519_verify(cond->signature, visitor.msg, visitor.msgLength, cond->publicKey); } static int cc_ed25519VerifyTree(const CC *cond, const unsigned char *msg, size_t msgLength) { CCVisitor visitor = {&ed25519Verify, msg, msgLength, NULL}; return cc_visit((CC*) cond, visitor); } /* * Signing data */ typedef struct CCEd25519SigningData { unsigned char *pk; unsigned char *skpk; int nSigned; } CCEd25519SigningData; /* * Visitor that signs an ed25519 condition if it has a matching public key */ static int ed25519Sign(CC *cond, CCVisitor visitor) { if (cond->type->typeId != CC_Ed25519Type.typeId) return 1; CCEd25519SigningData *signing = (CCEd25519SigningData*) visitor.context; if (0 != memcmp(cond->publicKey, signing->pk, 32)) return 1; if (!cond->signature) cond->signature = calloc(1,64); ed25519_sign(cond->signature, visitor.msg, visitor.msgLength, signing->pk, signing->skpk); signing->nSigned++; return 1; } /* * Sign ed25519 conditions in a tree */ int cc_signTreeEd25519(CC *cond, const unsigned char *privateKey, const unsigned char *msg, const size_t msgLength) { unsigned char pk[32], skpk[64]; ed25519_create_keypair(pk, skpk, privateKey); CCEd25519SigningData signing = {pk, skpk, 0}; CCVisitor visitor = {&ed25519Sign, (unsigned char*)msg, msgLength, &signing}; cc_visit(cond, visitor); return signing.nSigned; } static unsigned long ed25519Cost(const CC *cond) { return 131072; } static CC *ed25519FromJSON(const cJSON *params, char *err) { size_t binsz; cJSON *pk_item = cJSON_GetObjectItem(params, "publicKey"); if (!cJSON_IsString(pk_item)) { strcpy(err, "publicKey must be a string"); return NULL; } unsigned char *pk = base64_decode(pk_item->valuestring, &binsz); if (32 != binsz) { strcpy(err, "publicKey has incorrect length"); free(pk); return NULL; } cJSON *signature_item = cJSON_GetObjectItem(params, "signature"); unsigned char *sig = NULL; if (signature_item && !cJSON_IsNull(signature_item)) { if (!cJSON_IsString(signature_item)) { strcpy(err, "signature must be null or a string"); return NULL; } sig = base64_decode(signature_item->valuestring, &binsz); if (64 != binsz) { strcpy(err, "signature has incorrect length"); free(sig); return NULL; } } CC *cond = cc_new(CC_Ed25519); cond->publicKey = pk; cond->signature = sig; return cond; } static void ed25519ToJSON(const CC *cond, cJSON *params) { unsigned char *b64 = base64_encode(cond->publicKey, 32); cJSON_AddItemToObject(params, "publicKey", cJSON_CreateString(b64)); free(b64); if (cond->signature) { b64 = base64_encode(cond->signature, 64); cJSON_AddItemToObject(params, "signature", cJSON_CreateString(b64)); free(b64); } } static CC *ed25519FromFulfillment(const Fulfillment_t *ffill) { CC *cond = cc_new(CC_Ed25519); cond->publicKey = calloc(1,32); memcpy(cond->publicKey, ffill->choice.ed25519Sha256.publicKey.buf, 32); cond->signature = calloc(1,64); memcpy(cond->signature, ffill->choice.ed25519Sha256.signature.buf, 64); return cond; } static Fulfillment_t *ed25519ToFulfillment(const CC *cond) { if (!cond->signature) { return NULL; } Fulfillment_t *ffill = calloc(1, sizeof(Fulfillment_t)); ffill->present = Fulfillment_PR_ed25519Sha256; Ed25519Sha512Fulfillment_t *ed2 = &ffill->choice.ed25519Sha256; OCTET_STRING_fromBuf(&ed2->publicKey, cond->publicKey, 32); OCTET_STRING_fromBuf(&ed2->signature, cond->signature, 64); return ffill; } int ed25519IsFulfilled(const CC *cond) { return cond->signature > 0; } static void ed25519Free(CC *cond) { free(cond->publicKey); if (cond->signature) { free(cond->signature); } } static uint32_t ed25519Subtypes(const CC *cond) { return 0; } struct CCType CC_Ed25519Type = { 4, "ed25519-sha-256", Condition_PR_ed25519Sha256, 0, &ed25519Fingerprint, &ed25519Cost, &ed25519Subtypes, &ed25519FromJSON, &ed25519ToJSON, &ed25519FromFulfillment, &ed25519ToFulfillment, &ed25519IsFulfilled, &ed25519Free };