Skip to content

Commit

Permalink
Fully replace Java mpw algorithm implementation with proxy to standar…
Browse files Browse the repository at this point in the history
…d C implementation.
  • Loading branch information
lhunath committed Jun 4, 2018
1 parent 6957d46 commit 882de54
Show file tree
Hide file tree
Showing 33 changed files with 361 additions and 436 deletions.
130 changes: 107 additions & 23 deletions core/c/src/mpw-jni.c
Original file line number Diff line number Diff line change
@@ -1,29 +1,113 @@
#include <string.h>

#include "mpw-jni.h"
#include "mpw-algorithm.h"
#include "mpw-util.h"

/** native int _scrypt(byte[] passwd, byte[] salt, int N, int r, int p, byte[] buf); */
JNIEXPORT jint JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1scrypt(JNIEnv *env, jobject obj,
jbyteArray passwd, jbyteArray salt, jint N, jint r, jint p, jbyteArray buf) {

jbyte *passwdBytes = (*env)->GetByteArrayElements( env, passwd, NULL );
jbyte *saltBytes = (*env)->GetByteArrayElements( env, salt, NULL );
const size_t keyLength = (*env)->GetArrayLength( env, buf );
const uint8_t *key = mpw_kdf_scrypt( keyLength,
(uint8_t *)passwdBytes, (size_t)(*env)->GetArrayLength( env, passwd ),
(uint8_t *)saltBytes, (size_t)(*env)->GetArrayLength( env, salt ),
(uint64_t)N, (uint32_t)r, (uint32_t)p );
(*env)->ReleaseByteArrayElements( env, passwd, passwdBytes, JNI_ABORT );
(*env)->ReleaseByteArrayElements( env, salt, saltBytes, JNI_ABORT );

if (!key)
return ERR;

jbyte *bufBytes = (*env)->GetByteArrayElements( env, buf, NULL );
memcpy( bufBytes, key, keyLength );
(*env)->ReleaseByteArrayElements( env, buf, bufBytes, JNI_OK );
mpw_free( &key, keyLength );

return OK;
// TODO: We may need to zero the jbytes safely.

/* native int _masterKey(final String fullName, final byte[] masterPassword, final Version version) */
JNIEXPORT jbyteArray JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1masterKey(JNIEnv *env, jobject obj,
jstring fullName, jbyteArray masterPassword, jint algorithmVersion) {

const char *fullNameString = (*env)->GetStringUTFChars( env, fullName, NULL );
jbyte *masterPasswordString = (*env)->GetByteArrayElements( env, masterPassword, NULL );

MPMasterKey masterKeyBytes = mpw_masterKey( fullNameString, (char *)masterPasswordString, (MPAlgorithmVersion)algorithmVersion );
(*env)->ReleaseStringUTFChars( env, fullName, fullNameString );
(*env)->ReleaseByteArrayElements( env, masterPassword, masterPasswordString, JNI_ABORT );

if (!masterKeyBytes)
return NULL;

jbyteArray masterKey = (*env)->NewByteArray( env, (jsize)MPMasterKeySize );
(*env)->SetByteArrayRegion( env, masterKey, 0, (jsize)MPMasterKeySize, (jbyte *)masterKeyBytes );
mpw_free( &masterKeyBytes, MPMasterKeySize );

return masterKey;
}

/* native int _siteKey(final byte[] masterKey, final String siteName, final long siteCounter,
final MPKeyPurpose keyPurpose, @Nullable final String keyContext, final Version version) */
JNIEXPORT jbyteArray JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1siteKey(JNIEnv *env, jobject obj,
jbyteArray masterKey, jstring siteName, jlong siteCounter, jint keyPurpose, jstring keyContext, jint algorithmVersion) {

jbyte *masterKeyBytes = (*env)->GetByteArrayElements( env, masterKey, NULL );
const char *siteNameString = (*env)->GetStringUTFChars( env, siteName, NULL );
const char *keyContextString = keyContext? (*env)->GetStringUTFChars( env, keyContext, NULL ): NULL;
MPMasterKey siteKeyBytes = mpw_siteKey(
(MPMasterKey)masterKeyBytes, siteNameString, (MPCounterValue)siteCounter,
(MPKeyPurpose)keyPurpose, keyContextString, (MPAlgorithmVersion)algorithmVersion );
(*env)->ReleaseByteArrayElements( env, masterKey, masterKeyBytes, JNI_ABORT );
(*env)->ReleaseStringUTFChars( env, siteName, siteNameString );
(*env)->ReleaseStringUTFChars( env, keyContext, keyContextString );

if (!siteKeyBytes)
return NULL;

jbyteArray siteKey = (*env)->NewByteArray( env, (jsize)MPMasterKeySize );
(*env)->SetByteArrayRegion( env, siteKey, 0, (jsize)MPMasterKeySize, (jbyte *)siteKeyBytes );
mpw_free( &siteKeyBytes, MPSiteKeySize );

return siteKey;
}

/* native String _siteResult(final byte[] masterKey, final byte[] siteKey, final String siteName, final long siteCounter,
final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
final MPResultType resultType, @Nullable final String resultParam, final Version version) */
JNIEXPORT jstring JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1siteResult(JNIEnv *env, jobject obj,
jbyteArray masterKey, jbyteArray siteKey, jstring siteName, jlong siteCounter, jint keyPurpose, jstring keyContext,
jint resultType, jstring resultParam, jint algorithmVersion) {

jbyte *masterKeyBytes = (*env)->GetByteArrayElements( env, masterKey, NULL );
jbyte *siteKeyBytes = (*env)->GetByteArrayElements( env, siteKey, NULL );
const char *siteNameString = (*env)->GetStringUTFChars( env, siteName, NULL );
const char *keyContextString = keyContext? (*env)->GetStringUTFChars( env, keyContext, NULL ): NULL;
const char *resultParamString = resultParam? (*env)->GetStringUTFChars( env, resultParam, NULL ): NULL;
const char *siteResultString = mpw_siteResult(
(MPMasterKey)masterKeyBytes, siteNameString, (MPCounterValue)siteCounter,
(MPKeyPurpose)keyPurpose, keyContextString, (MPResultType)resultType, resultParamString, (MPAlgorithmVersion)algorithmVersion );
(*env)->ReleaseByteArrayElements( env, masterKey, masterKeyBytes, JNI_ABORT );
(*env)->ReleaseByteArrayElements( env, siteKey, siteKeyBytes, JNI_ABORT );
(*env)->ReleaseStringUTFChars( env, siteName, siteNameString );
(*env)->ReleaseStringUTFChars( env, keyContext, keyContextString );
(*env)->ReleaseStringUTFChars( env, resultParam, resultParamString );

if (!siteResultString)
return NULL;

jstring siteResult = (*env)->NewStringUTF( env, siteResultString );
mpw_free_string( &siteResultString );

return siteResult;
}

/* native String _siteState(final byte[] masterKey, final byte[] siteKey, final String siteName, final long siteCounter,
final MPKeyPurpose keyPurpose, @Nullable final String keyContext,
final MPResultType resultType, final String resultParam, final Version version) */
JNIEXPORT jstring JNICALL Java_com_lyndir_masterpassword_impl_MPAlgorithmV0__1siteState(JNIEnv *env, jobject obj,
jbyteArray masterKey, jbyteArray siteKey, jstring siteName, jlong siteCounter, jint keyPurpose, jstring keyContext,
jint resultType, jstring resultParam, jint algorithmVersion) {

jbyte *masterKeyBytes = (*env)->GetByteArrayElements( env, masterKey, NULL );
jbyte *siteKeyBytes = (*env)->GetByteArrayElements( env, siteKey, NULL );
const char *siteNameString = (*env)->GetStringUTFChars( env, siteName, NULL );
const char *keyContextString = keyContext? (*env)->GetStringUTFChars( env, keyContext, NULL ): NULL;
const char *resultParamString = (*env)->GetStringUTFChars( env, resultParam, NULL );
const char *siteStateString = mpw_siteState(
(MPMasterKey)masterKeyBytes, siteNameString, (MPCounterValue)siteCounter,
(MPKeyPurpose)keyPurpose, keyContextString, (MPResultType)resultType, resultParamString, (MPAlgorithmVersion)algorithmVersion );
(*env)->ReleaseByteArrayElements( env, masterKey, masterKeyBytes, JNI_ABORT );
(*env)->ReleaseByteArrayElements( env, siteKey, siteKeyBytes, JNI_ABORT );
(*env)->ReleaseStringUTFChars( env, siteName, siteNameString );
(*env)->ReleaseStringUTFChars( env, keyContext, keyContextString );
(*env)->ReleaseStringUTFChars( env, resultParam, resultParamString );

if (!siteStateString)
return NULL;

jstring siteState = (*env)->NewStringUTF( env, siteStateString );
mpw_free_string( &siteStateString );

return siteState;
}
32 changes: 28 additions & 4 deletions core/c/src/mpw-jni.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion core/java/algorithm/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ dependencies {

api group: 'com.fasterxml.jackson.core', name: 'jackson-annotations', version: '2.9.5'
api group: 'org.jetbrains', name: 'annotations', version: '13.0'
api group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.1'
api group: 'com.google.code.findbugs', name: 'jsr305', version: '3.0.2'
api group: 'com.google.code.findbugs', name: 'findbugs-annotations', version: '3.0.1'

lib project( path: ':masterpassword-core', configuration: 'default' )
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public abstract class MPAlgorithm {
* @param fullName The name of the user whose identity is described by the key.
* @param masterPassword The user's secret that authenticates his access to the identity.
*/
@Nullable
public abstract byte[] masterKey(String fullName, char[] masterPassword);

/**
Expand All @@ -54,6 +55,7 @@ public abstract class MPAlgorithm {
* @param keyPurpose The action that the user aims to undertake with this key.
* @param keyContext An action-specific context within which to scope the key.
*/
@Nullable
public abstract byte[] siteKey(byte[] masterKey, String siteName, UnsignedInteger siteCounter,
MPKeyPurpose keyPurpose, @Nullable String keyContext);

Expand All @@ -63,31 +65,11 @@ public abstract byte[] siteKey(byte[] masterKey, String siteName, UnsignedIntege
* @param resultType The template to base the site key's encoding on.
* @param resultParam A parameter that provides contextual data specific to the type template.
*/
@Nullable
public abstract String siteResult(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter,
MPKeyPurpose keyPurpose, @Nullable String keyContext,
MPResultType resultType, @Nullable String resultParam);

/**
* The result for {@link #siteResult(byte[], byte[], String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)}
* for the case where {@code resultType} is a {@link MPResultTypeClass#Template}.
*/
public abstract String siteResultFromTemplate(byte[] masterKey, byte[] siteKey,
MPResultType resultType, @Nullable String resultParam);

/**
* The result for {@link #siteResult(byte[], byte[], String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)}
* for the case where {@code resultType} is a {@link MPResultTypeClass#Stateful}.
*/
public abstract String siteResultFromState(byte[] masterKey, byte[] siteKey,
MPResultType resultType, String resultParam);

/**
* The result for {@link #siteResult(byte[], byte[], String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)}
* for the case where {@code resultType} is a {@link MPResultTypeClass#Derive}.
*/
public abstract String siteResultFromDerive(byte[] masterKey, byte[] siteKey,
MPResultType resultType, @Nullable String resultParam);

/**
* For {@link MPResultTypeClass#Stateful} {@code resultType}s, generate the {@code resultParam} to use with the
* {@link #siteResult(byte[], byte[], String, UnsignedInteger, MPKeyPurpose, String, MPResultType, String)} call
Expand All @@ -96,6 +78,7 @@ public abstract String siteResultFromDerive(byte[] masterKey, byte[] siteKey,
* @param resultType The template to base the site key's encoding on.
* @param resultParam A parameter that provides contextual data specific to the type template.
*/
@Nullable
public abstract String siteState(byte[] masterKey, byte[] siteKey, String siteName, UnsignedInteger siteCounter,
MPKeyPurpose keyPurpose, @Nullable String keyContext,
MPResultType resultType, String resultParam);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================

package com.lyndir.masterpassword;

/**
* @author lhunath, 2017-09-21
*/
public class MPAlgorithmException extends MPException {

public MPAlgorithmException(final String message) {
super( message );
}

public MPAlgorithmException(final String message, final Throwable cause) {
super( message, cause );
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//==============================================================================
// This file is part of Master Password.
// Copyright (c) 2011-2017, Maarten Billemont.
//
// Master Password is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Master Password is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You can find a copy of the GNU General Public License in the
// LICENSE file. Alternatively, see <http://www.gnu.org/licenses/>.
//==============================================================================

package com.lyndir.masterpassword;

/**
* @author lhunath, 2018-06-03
*/
public class MPException extends Exception {

public MPException(final String message) {
super( message );
}

public MPException(final String message, final Throwable cause) {
super( message, cause );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,13 @@
/**
* @author lhunath, 2017-09-21
*/
public class MPKeyUnavailableException extends Exception {
public class MPKeyUnavailableException extends MPException {

public MPKeyUnavailableException(final String message) {
super( message );
}

public MPKeyUnavailableException(final String message, final Throwable cause) {
super( message, cause );
}
}
Loading

0 comments on commit 882de54

Please sign in to comment.