2 * Copyright (C) 2016 Andreas Steffen
3 * HSR Hochschule fuer Technik Rapperswil
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 #include "curve25519_private_key.h"
17 #include "curve25519_public_key.h"
18 #include "ref10/ref10.h"
20 #include <asn1/asn1.h>
26 typedef struct private_curve25519_private_key_t private_curve25519_private_key_t
;
29 * Private data of a curve25519_private_key_t object.
31 struct private_curve25519_private_key_t
{
33 * Public interface for this signer.
35 curve25519_private_key_t
public;
38 * Secret scalar s derived from private key.
40 uint8_t s
[HASH_SIZE_SHA512
];
58 METHOD(private_key_t
, get_type
, key_type_t
,
59 private_curve25519_private_key_t
*this)
64 METHOD(private_key_t
, sign
, bool,
65 private_curve25519_private_key_t
*this, signature_scheme_t scheme
,
66 void *params
, chunk_t data
, chunk_t
*signature
)
68 uint8_t r
[HASH_SIZE_SHA512
], k
[HASH_SIZE_SHA512
], sig
[HASH_SIZE_SHA512
];
74 if (scheme
!= SIGN_ED25519
)
76 DBG1(DBG_LIB
, "signature scheme %N not supported by Ed25519",
77 signature_scheme_names
, scheme
);
81 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA512
);
86 prefix
= chunk_create(this->s
+ 32, 32);
88 if (!hasher
->get_hash(hasher
, prefix
, NULL
) ||
89 !hasher
->get_hash(hasher
, data
, r
))
94 ge_scalarmult_base(&R
, r
);
95 ge_p3_tobytes(sig
, &R
);
97 if (!hasher
->get_hash(hasher
, chunk_create(sig
, 32), NULL
) ||
98 !hasher
->get_hash(hasher
, this->pubkey
, NULL
) ||
99 !hasher
->get_hash(hasher
, data
, k
))
104 sc_muladd(sig
+ 32, k
, this->s
, r
);
106 *signature
= chunk_clone(chunk_create(sig
, sizeof(sig
)));
110 hasher
->destroy(hasher
);
114 METHOD(private_key_t
, decrypt
, bool,
115 private_curve25519_private_key_t
*this, encryption_scheme_t scheme
,
116 chunk_t crypto
, chunk_t
*plain
)
118 DBG1(DBG_LIB
, "encryption scheme %N not supported", encryption_scheme_names
,
123 METHOD(private_key_t
, get_keysize
, int,
124 private_curve25519_private_key_t
*this)
126 return 8 * ED25519_KEY_LEN
;
129 METHOD(private_key_t
, get_public_key
, public_key_t
*,
130 private_curve25519_private_key_t
*this)
132 public_key_t
*public;
135 pubkey
= curve25519_public_key_info_encode(this->pubkey
);
136 public = lib
->creds
->create(lib
->creds
, CRED_PUBLIC_KEY
, KEY_ED25519
,
137 BUILD_BLOB_ASN1_DER
, pubkey
, BUILD_END
);
143 METHOD(private_key_t
, get_encoding
, bool,
144 private_curve25519_private_key_t
*this, cred_encoding_type_t type
,
149 case PRIVKEY_ASN1_DER
:
154 *encoding
= asn1_wrap(ASN1_SEQUENCE
, "cms",
156 asn1_algorithmIdentifier(OID_ED25519
),
157 asn1_wrap(ASN1_OCTET_STRING
, "s",
158 asn1_simple_object(ASN1_OCTET_STRING
, this->key
)
161 if (type
== PRIVKEY_PEM
)
163 chunk_t asn1_encoding
= *encoding
;
165 success
= lib
->encoding
->encode(lib
->encoding
, PRIVKEY_PEM
,
166 NULL
, encoding
, CRED_PART_EDDSA_PRIV_ASN1_DER
,
167 asn1_encoding
, CRED_PART_END
);
168 chunk_clear(&asn1_encoding
);
177 METHOD(private_key_t
, get_fingerprint
, bool,
178 private_curve25519_private_key_t
*this, cred_encoding_type_t type
,
183 if (lib
->encoding
->get_cache(lib
->encoding
, type
, this, fp
))
187 success
= curve25519_public_key_fingerprint(this->pubkey
, type
, fp
);
190 lib
->encoding
->cache(lib
->encoding
, type
, this, *fp
);
195 METHOD(private_key_t
, get_ref
, private_key_t
*,
196 private_curve25519_private_key_t
*this)
199 return &this->public.key
;
202 METHOD(private_key_t
, destroy
, void,
203 private_curve25519_private_key_t
*this)
205 if (ref_put(&this->ref
))
207 lib
->encoding
->clear_cache(lib
->encoding
, this);
208 memwipe(this->s
, HASH_SIZE_SHA512
);
209 chunk_clear(&this->key
);
210 chunk_free(&this->pubkey
);
216 * Internal generic constructor
218 static private_curve25519_private_key_t
*curve25519_private_key_create(chunk_t key
)
220 private_curve25519_private_key_t
*this;
224 /* derive public key from private key */
225 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA512
);
235 .get_type
= _get_type
,
238 .get_keysize
= _get_keysize
,
239 .get_public_key
= _get_public_key
,
240 .equals
= private_key_equals
,
241 .belongs_to
= private_key_belongs_to
,
242 .get_fingerprint
= _get_fingerprint
,
243 .has_fingerprint
= private_key_has_fingerprint
,
244 .get_encoding
= _get_encoding
,
250 .pubkey
= chunk_alloc(ED25519_KEY_LEN
),
254 /* derive secret scalar s from private key */
255 if (!hasher
->get_hash(hasher
, key
, this->s
))
258 hasher
->destroy(hasher
);
261 hasher
->destroy(hasher
);
267 /* derive public key */
268 ge_scalarmult_base(&A
, this->s
);
269 ge_p3_tobytes(this->pubkey
.ptr
, &A
);
277 curve25519_private_key_t
*curve25519_private_key_gen(key_type_t type
,
280 private_curve25519_private_key_t
*this;
286 switch (va_arg(args
, builder_part_t
))
289 /* key_size argument is not needed */
300 /* generate 256 bit true random private key */
301 rng
= lib
->crypto
->create_rng(lib
->crypto
, RNG_TRUE
);
302 if (!rng
|| !rng
->allocate_bytes(rng
, ED25519_KEY_LEN
, &key
))
309 this = curve25519_private_key_create(key
);
311 return this ? &this->public : NULL
;
317 curve25519_private_key_t
*curve25519_private_key_load(key_type_t type
,
320 private_curve25519_private_key_t
*this;
321 chunk_t key
= chunk_empty
;
325 switch (va_arg(args
, builder_part_t
))
327 case BUILD_EDDSA_PRIV_ASN1_DER
:
328 key
= va_arg(args
, chunk_t
);
338 if (!asn1_parse_simple_object(&key
, ASN1_OCTET_STRING
, 0, "EdPrivateKey") ||
339 key
.len
!= ED25519_KEY_LEN
)
343 this = curve25519_private_key_create(chunk_clone(key
));
345 return this ? &this->public : NULL
;