aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Baker <dbkr@users.noreply.github.com>2018-10-12 08:24:45 +0100
committerGitHub <noreply@github.com>2018-10-12 08:24:45 +0100
commitb1130fb77f0bcaa436a5308bd1093b0e94aa6585 (patch)
tree0224871c07b0a98989e122c1937606a1857a2aa4
parentb2d91f55ece853ca1a398d3c6814f18a3f10bee0 (diff)
parent50ed20f61e76c4569c001cf8acb6e5bc361957b3 (diff)
Merge pull request #61 from matrix-org/dbkr/pk_private_export_import
Work with PkDecryption keys by their private keys
-rw-r--r--CHANGELOG.rst4
-rw-r--r--include/olm/error.h7
-rw-r--r--include/olm/pk.h48
-rw-r--r--javascript/olm_pk.js32
-rw-r--r--javascript/olm_pre.js1
-rw-r--r--javascript/test/pk.spec.js14
-rw-r--r--src/error.c1
-rw-r--r--src/pk.cpp41
-rw-r--r--tests/test_pk.cpp9
9 files changed, 138 insertions, 19 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9160ff1..6b450b4 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,10 @@ started up asynchronously. The imported module now has an init()
method which returns a promise. The library cannot be used until
this promise resolves. It will reject if the library fails to start.
+olm_pk_generate_key() and olm_pk_generate_key_random_length() have
+been removed: to generate a random key, use olm_pk_key_from_private()
+with random bytes as the private key.
+
Changes in `2.3.0 <http://matrix.org/git/olm/commit/?h=2.3.0>`_
This release includes the following changes since 2.2.2:
diff --git a/include/olm/error.h b/include/olm/error.h
index 9d44a94..ee2187c 100644
--- a/include/olm/error.h
+++ b/include/olm/error.h
@@ -51,6 +51,13 @@ enum OlmErrorCode {
*/
OLM_BAD_SIGNATURE = 14,
+ OLM_INPUT_BUFFER_TOO_SMALL = 15,
+
+ // Not an error code, just here to pad out the enum past 16 because
+ // otherwise the compiler warns about a redunant check. If you're
+ // adding an error code, replace this one!
+ OLM_ERROR_NOT_INVENTED_YET = 16,
+
/* remember to update the list of string constants in error.c when updating
* this list. */
};
diff --git a/include/olm/pk.h b/include/olm/pk.h
index 8804d1f..4278fca 100644
--- a/include/olm/pk.h
+++ b/include/olm/pk.h
@@ -80,7 +80,7 @@ size_t olm_pk_encrypt_random_length(
* key. Returns olm_error() on failure. If the ciphertext, mac, or
* ephemeral_key buffers were too small then olm_pk_encryption_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
- * olm_pk_encryption_last_error() will be "NOT_ENOUGH_RANDOM". */
+ * olm_pk_encryption_last_error() will be "OLM_INPUT_BUFFER_TOO_SMALL". */
size_t olm_pk_encrypt(
OlmPkEncryption *encryption,
void const * plaintext, size_t plaintext_length,
@@ -112,19 +112,36 @@ size_t olm_clear_pk_decryption(
OlmPkDecryption *decryption
);
-/** The number of random bytes needed to generate a new key. */
+/** Get the number of bytes required to store an olm private key
+ */
+size_t olm_pk_private_key_length();
+
+/** DEPRECATED: Use olm_pk_private_key_length()
+ */
size_t olm_pk_generate_key_random_length(void);
-/** Generate a new key pair to use for decrypting messages. The private key is
- * stored in the decryption object, and the associated public key will be
- * written to the pubkey buffer. Returns olm_error() on failure. If the pubkey
- * buffer is too small then olm_pk_decryption_last_error() will be
- * "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
- * olm_pk_decryption_last_error() will be "NOT_ENOUGH_RANDOM". */
+/** Initialise the key from the private part of a key as returned by
+ * olm_pk_get_private_key(). The associated public key will be written to the
+ * pubkey buffer. Returns olm_error() on failure. If the pubkey buffer is too
+ * small then olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
+ * If the private key was not long enough then olm_pk_decryption_last_error()
+ * will be "OLM_INPUT_BUFFER_TOO_SMALL".
+ *
+ * Note that the pubkey is a base64 encoded string, but the private key is
+ * an unencoded byte array
+ */
+size_t olm_pk_key_from_private(
+ OlmPkDecryption * decryption,
+ void * pubkey, size_t pubkey_length,
+ void * privkey, size_t privkey_length
+);
+
+/** DEPRECATED: Use olm_pk_key_from_private
+ */
size_t olm_pk_generate_key(
OlmPkDecryption * decryption,
void * pubkey, size_t pubkey_length,
- void * random, size_t random_length
+ void * privkey, size_t privkey_length
);
/** Returns the number of bytes needed to store a decryption object. */
@@ -177,6 +194,19 @@ size_t olm_pk_decrypt(
void * plaintext, size_t max_plaintext_length
);
+/**
+ * Get the private key for an OlmDecryption object as an unencoded byte array
+ * private_key must be a pointer to a buffer of at least
+ * olm_pk_private_key_length() bytes and this length must be passed in
+ * private_key_length. If the given buffer is too small, returns olm_error()
+ * and olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
+ * Returns the number of bytes written.
+ */
+size_t olm_pk_get_private_key(
+ OlmPkDecryption * decryption,
+ void *private_key, size_t private_key_length
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/javascript/olm_pk.js b/javascript/olm_pk.js
index 5a2c7dc..4f730dd 100644
--- a/javascript/olm_pk.js
+++ b/javascript/olm_pk.js
@@ -118,16 +118,32 @@ PkDecryption.prototype['free'] = function() {
free(this.ptr);
}
+PkDecryption.prototype['init_with_private_key'] = restore_stack(function (private_key) {
+ var private_key_buffer = stack(private_key.length);
+ Module['HEAPU8'].set(private_key, private_key_buffer);
+
+ var pubkey_length = pk_decryption_method(
+ Module['_olm_pk_key_length']
+ )();
+ var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
+ pk_decryption_method(Module['_olm_pk_key_from_private'])(
+ this.ptr,
+ pubkey_buffer, pubkey_length,
+ private_key_buffer, private_key.length
+ );
+ return Pointer_stringify(pubkey_buffer);
+});
+
PkDecryption.prototype['generate_key'] = restore_stack(function () {
var random_length = pk_decryption_method(
- Module['_olm_pk_generate_key_random_length']
+ Module['_olm_pk_private_key_length']
)();
var random_buffer = random_stack(random_length);
var pubkey_length = pk_decryption_method(
Module['_olm_pk_key_length']
)();
var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
- pk_decryption_method(Module['_olm_pk_generate_key'])(
+ pk_decryption_method(Module['_olm_pk_key_from_private'])(
this.ptr,
pubkey_buffer, pubkey_length,
random_buffer, random_length
@@ -135,6 +151,18 @@ PkDecryption.prototype['generate_key'] = restore_stack(function () {
return Pointer_stringify(pubkey_buffer);
});
+PkDecryption.prototype['get_private_key'] = restore_stack(function () {
+ var privkey_length = pk_encryption_method(
+ Module['_olm_pk_private_key_length']
+ )();
+ var privkey_buffer = stack(privkey_length);
+ pk_decryption_method(Module['_olm_pk_get_private_key'])(
+ this.ptr,
+ privkey_buffer, privkey_length
+ );
+ return new Uint8Array(Module['HEAPU8'].buffer, privkey_buffer, privkey_length);
+});
+
PkDecryption.prototype['pickle'] = restore_stack(function (key) {
var key_array = array_from_string(key);
var pickle_length = pk_decryption_method(
diff --git a/javascript/olm_pre.js b/javascript/olm_pre.js
index 18d836d..314d7da 100644
--- a/javascript/olm_pre.js
+++ b/javascript/olm_pre.js
@@ -40,6 +40,7 @@ var NULL_BYTE_PADDING_LENGTH = 1;
Module['onRuntimeInitialized'] = function() {
OLM_ERROR = Module['_olm_error']();
+ olm_exports["PRIVATE_KEY_LENGTH"] = Module['_olm_pk_private_key_length']();
if (onInitSuccess) onInitSuccess();
};
diff --git a/javascript/test/pk.spec.js b/javascript/test/pk.spec.js
index 34f7be5..b4b119e 100644
--- a/javascript/test/pk.spec.js
+++ b/javascript/test/pk.spec.js
@@ -41,6 +41,20 @@ describe("pk", function() {
}
});
+ it('should import & export keys from private parts', function () {
+ var alice_private = new Uint8Array([
+ 0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
+ 0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
+ 0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
+ 0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
+ ]);
+ var alice_public = decryption.init_with_private_key(alice_private);
+ expect(alice_public).toEqual("hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo");
+
+ var alice_private_out = decryption.get_private_key();
+ expect(alice_private_out).toEqual(alice_private);
+ });
+
it('should encrypt and decrypt', function () {
var TEST_TEXT='têst1';
var pubkey = decryption.generate_key();
diff --git a/src/error.c b/src/error.c
index f541a93..5147b5c 100644
--- a/src/error.c
+++ b/src/error.c
@@ -31,6 +31,7 @@ static const char * ERRORS[] = {
"UNKNOWN_MESSAGE_INDEX",
"BAD_LEGACY_ACCOUNT_PICKLE",
"BAD_SIGNATURE",
+ "OLM_INPUT_BUFFER_TOO_SMALL",
};
const char * _olm_error_to_string(enum OlmErrorCode error)
diff --git a/src/pk.cpp b/src/pk.cpp
index 4c5f50e..5cfcea2 100644
--- a/src/pk.cpp
+++ b/src/pk.cpp
@@ -187,31 +187,35 @@ size_t olm_clear_pk_decryption(
return sizeof(OlmPkDecryption);
}
-size_t olm_pk_generate_key_random_length(void) {
+size_t olm_pk_private_key_length(void) {
return CURVE25519_KEY_LENGTH;
}
+size_t olm_pk_generate_key_random_length(void) {
+ return olm_pk_private_key_length();
+}
+
size_t olm_pk_key_length(void) {
return olm::encode_base64_length(CURVE25519_KEY_LENGTH);
}
-size_t olm_pk_generate_key(
+size_t olm_pk_key_from_private(
OlmPkDecryption * decryption,
void * pubkey, size_t pubkey_length,
- void * random, size_t random_length
+ void * privkey, size_t privkey_length
) {
if (pubkey_length < olm_pk_key_length()) {
decryption->last_error =
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
- if (random_length < olm_pk_generate_key_random_length()) {
+ if (privkey_length < olm_pk_private_key_length()) {
decryption->last_error =
- OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
+ OlmErrorCode::OLM_INPUT_BUFFER_TOO_SMALL;
return std::size_t(-1);
}
- _olm_crypto_curve25519_generate_key((uint8_t *) random, &decryption->key_pair);
+ _olm_crypto_curve25519_generate_key((uint8_t *) privkey, &decryption->key_pair);
olm::encode_base64(
(const uint8_t *)decryption->key_pair.public_key.public_key,
CURVE25519_KEY_LENGTH,
@@ -220,6 +224,14 @@ size_t olm_pk_generate_key(
return 0;
}
+size_t olm_pk_generate_key(
+ OlmPkDecryption * decryption,
+ void * pubkey, size_t pubkey_length,
+ void * privkey, size_t privkey_length
+) {
+ return olm_pk_key_from_private(decryption, pubkey, pubkey_length, privkey, privkey_length);
+}
+
namespace {
static const std::uint32_t PK_DECRYPTION_PICKLE_VERSION = 1;
@@ -380,4 +392,21 @@ size_t olm_pk_decrypt(
}
}
+size_t olm_pk_get_private_key(
+ OlmPkDecryption * decryption,
+ void *private_key, size_t private_key_length
+) {
+ if (private_key_length < olm_pk_private_key_length()) {
+ decryption->last_error =
+ OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
+ return std::size_t(-1);
+ }
+ std::memcpy(
+ private_key,
+ decryption->key_pair.private_key.private_key,
+ olm_pk_private_key_length()
+ );
+ return olm_pk_private_key_length();
+}
+
}
diff --git a/tests/test_pk.cpp b/tests/test_pk.cpp
index ee12603..42cc8c9 100644
--- a/tests/test_pk.cpp
+++ b/tests/test_pk.cpp
@@ -36,7 +36,7 @@ const std::uint8_t *bob_public = (std::uint8_t *) "3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbe
std::uint8_t pubkey[::olm_pk_key_length()];
-olm_pk_generate_key(
+olm_pk_key_from_private(
decryption,
pubkey, sizeof(pubkey),
alice_private, sizeof(alice_private)
@@ -44,6 +44,11 @@ olm_pk_generate_key(
assert_equals(alice_public, pubkey, olm_pk_key_length());
+uint8_t *alice_private_back_out = (uint8_t *)malloc(olm_pk_private_key_length());
+olm_pk_get_private_key(decryption, alice_private_back_out, olm_pk_private_key_length());
+assert_equals(alice_private, alice_private_back_out, olm_pk_private_key_length());
+free(alice_private_back_out);
+
std::uint8_t encryption_buffer[olm_pk_encryption_size()];
OlmPkEncryption *encryption = olm_pk_encryption(encryption_buffer);
@@ -105,7 +110,7 @@ const std::uint8_t *alice_public = (std::uint8_t *) "hSDwCYkwp1R0i33ctD73Wg2/Og0
std::uint8_t pubkey[olm_pk_key_length()];
-olm_pk_generate_key(
+olm_pk_key_from_private(
decryption,
pubkey, sizeof(pubkey),
alice_private, sizeof(alice_private)