Implement algorithm support for hybrid personal passwords.
This commit is contained in:
parent
228f8e4ed1
commit
322e056661
171
core/c/base64.c
Normal file
171
core/c/base64.c
Normal file
@ -0,0 +1,171 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1995-1999 The Apache Group. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the Apache Group
|
||||
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
*
|
||||
* 4. The names "Apache Server" and "Apache Group" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the Apache Group
|
||||
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Group and was originally based
|
||||
* on public domain software written at the National Center for
|
||||
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
|
||||
* For more information on the Apache Group and the Apache HTTP server
|
||||
* project, please see <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
#include "base64.h"
|
||||
|
||||
/* aaaack but it's fast and const should make it shared text page. */
|
||||
static const unsigned char pr2six[256] =
|
||||
{
|
||||
/* ASCII table */
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
|
||||
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
|
||||
64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
|
||||
64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
||||
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
|
||||
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
|
||||
};
|
||||
|
||||
size_t Base64decode_len(const char *bufcoded) {
|
||||
|
||||
size_t nbytesdecoded;
|
||||
register const unsigned char *bufin;
|
||||
register int nprbytes;
|
||||
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
while (pr2six[*(bufin++)] <= 63);
|
||||
|
||||
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1;
|
||||
nbytesdecoded = (size_t)(((nprbytes + 3) / 4) * 3);
|
||||
|
||||
return nbytesdecoded;
|
||||
}
|
||||
|
||||
int Base64decode(uint8_t *bufplain, const char *bufcoded) {
|
||||
|
||||
int nbytesdecoded;
|
||||
register const unsigned char *bufin;
|
||||
register unsigned char *bufout;
|
||||
register int nprbytes;
|
||||
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
while (pr2six[*(bufin++)] <= 63);
|
||||
nprbytes = (int)(bufin - (const unsigned char *)bufcoded) - 1;
|
||||
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
|
||||
|
||||
bufout = bufplain;
|
||||
bufin = (const unsigned char *)bufcoded;
|
||||
|
||||
while (nprbytes > 4) {
|
||||
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||||
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||||
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||||
bufin += 4;
|
||||
nprbytes -= 4;
|
||||
}
|
||||
|
||||
/* Note: (nprbytes == 1) would be an error, so just ingore that case */
|
||||
if (nprbytes > 1) {
|
||||
*(bufout++) = (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
|
||||
}
|
||||
if (nprbytes > 2) {
|
||||
*(bufout++) = (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
|
||||
}
|
||||
if (nprbytes > 3) {
|
||||
*(bufout++) = (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
|
||||
}
|
||||
|
||||
nbytesdecoded -= (4 - nprbytes) & 3;
|
||||
return nbytesdecoded;
|
||||
}
|
||||
|
||||
static const char basis_64[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
size_t Base64encode_len(size_t len) {
|
||||
|
||||
return ((len + 2) / 3 * 4);
|
||||
}
|
||||
|
||||
int Base64encode(char *encoded, const uint8_t *string, size_t len) {
|
||||
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = encoded;
|
||||
for (i = 0; i < len - 2; i += 3) {
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) |
|
||||
((string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2) |
|
||||
((string[i + 2] & 0xC0) >> 6)];
|
||||
*p++ = basis_64[string[i + 2] & 0x3F];
|
||||
}
|
||||
if (i < len) {
|
||||
*p++ = basis_64[(string[i] >> 2) & 0x3F];
|
||||
if (i == (len - 1)) {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4)];
|
||||
*p++ = '=';
|
||||
}
|
||||
else {
|
||||
*p++ = basis_64[((string[i] & 0x3) << 4) |
|
||||
((string[i + 1] & 0xF0) >> 4)];
|
||||
*p++ = basis_64[((string[i + 1] & 0xF) << 2)];
|
||||
}
|
||||
*p++ = '=';
|
||||
}
|
||||
|
||||
return (int)(p - encoded);
|
||||
}
|
64
core/c/base64.h
Normal file
64
core/c/base64.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1995-1999 The Apache Group. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the Apache Group
|
||||
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
*
|
||||
* 4. The names "Apache Server" and "Apache Group" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* apache@apache.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "Apache"
|
||||
* nor may "Apache" appear in their names without prior written
|
||||
* permission of the Apache Group.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the Apache Group
|
||||
* for use in the Apache HTTP server project (http://www.apache.org/)."
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This software consists of voluntary contributions made by many
|
||||
* individuals on behalf of the Apache Group and was originally based
|
||||
* on public domain software written at the National Center for
|
||||
* Supercomputing Applications, University of Illinois, Urbana-Champaign.
|
||||
* For more information on the Apache Group and the Apache HTTP server
|
||||
* project, please see <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
size_t Base64decode_len(const char *bufcoded);
|
||||
int Base64decode(uint8_t *bufplain, const char *bufcoded);
|
||||
|
||||
size_t Base64encode_len(size_t len);
|
||||
int Base64encode(char *encoded, const uint8_t *string, size_t len);
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "mpw-types.h"
|
||||
#include "mpw-util.h"
|
||||
#include "base64.h"
|
||||
|
||||
#define MP_N 32768
|
||||
#define MP_r 8
|
||||
@ -155,11 +156,38 @@ static const char *mpw_sitePassword_v0(
|
||||
const char *mpw_encrypt_v0(
|
||||
MPMasterKey masterKey, const char *plainText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
// Encrypt
|
||||
dbg( "-- encrypting plainText: %s\n", plainText );
|
||||
size_t bufSize = strlen( plainText );
|
||||
const uint8_t *cipherBuf = mpw_aes_encrypt( masterKey, MPMasterKeySize, (const uint8_t *)plainText, bufSize );
|
||||
dbg( "-- cipherBuf: %lu bytes = ", bufSize );
|
||||
printb( cipherBuf, bufSize );
|
||||
|
||||
// Base64-encode
|
||||
char *cipherText = calloc( 1, Base64encode_len( bufSize ) + 1 );
|
||||
Base64encode( cipherText, cipherBuf, bufSize );
|
||||
dbg( "-- b64 encoded -> cipherText: %s\n", cipherText );
|
||||
mpw_free( cipherBuf, bufSize );
|
||||
|
||||
return cipherText;
|
||||
}
|
||||
|
||||
const char *mpw_decrypt_v0(
|
||||
MPMasterKey masterKey, const char *cipherText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
// Base64-decode
|
||||
dbg( "-- decrypting cipherText: %s\n", cipherText );
|
||||
size_t bufSize = Base64decode_len( cipherText ) + 1;
|
||||
uint8_t *cipherBuf = calloc( 1, bufSize );
|
||||
Base64decode( cipherBuf, cipherText );
|
||||
dbg( "-- b64 decoded: %lu bytes = ", bufSize );
|
||||
printb( cipherBuf, bufSize );
|
||||
|
||||
|
||||
// Decrypt
|
||||
const char *plainText = (const char *)mpw_aes_decrypt( masterKey, MPMasterKeySize, cipherBuf, bufSize );
|
||||
dbg( "-- decrypted -> plainText: %s\n", plainText );
|
||||
mpw_free( cipherBuf, bufSize );
|
||||
|
||||
return plainText;
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v1(
|
||||
const char *mpw_encrypt_v1(
|
||||
MPMasterKey masterKey, const char *plainText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_encrypt_v0( masterKey, plainText );
|
||||
}
|
||||
|
||||
const char *mpw_decrypt_v1(
|
||||
MPMasterKey masterKey, const char *cipherText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_decrypt_v0( masterKey, cipherText );
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v2(
|
||||
const char *mpw_encrypt_v2(
|
||||
MPMasterKey masterKey, const char *plainText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_encrypt_v1( masterKey, plainText );
|
||||
}
|
||||
|
||||
const char *mpw_decrypt_v2(
|
||||
MPMasterKey masterKey, const char *cipherText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_decrypt_v1( masterKey, cipherText );
|
||||
}
|
||||
|
@ -136,11 +136,11 @@ static const char *mpw_sitePassword_v3(
|
||||
const char *mpw_encrypt_v3(
|
||||
MPMasterKey masterKey, const char *plainText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_encrypt_v2( masterKey, plainText );
|
||||
}
|
||||
|
||||
const char *mpw_decrypt_v3(
|
||||
MPMasterKey masterKey, const char *cipherText) {
|
||||
|
||||
return NULL; // TODO: aes128_cbc
|
||||
return mpw_decrypt_v2( masterKey, cipherText );
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ json_object *mpw_get_json_section(
|
||||
char *sectionTokenizer = strdup( section ), *sectionToken = sectionTokenizer;
|
||||
for (sectionToken = strtok( sectionToken, "." ); sectionToken; sectionToken = strtok( NULL, "." ))
|
||||
if (!json_object_object_get_ex( json_value, sectionToken, &json_value ) || !json_value) {
|
||||
dbg( "While resolving: %s: Missing value for: %s\n", section, sectionToken );
|
||||
trc( "While resolving: %s: Missing value for: %s\n", section, sectionToken );
|
||||
json_value = NULL;
|
||||
break;
|
||||
}
|
||||
|
@ -55,7 +55,8 @@ MPMarshalledSite *mpw_marshall_site(
|
||||
realloc( marshalledUser->sites, sizeof( MPMarshalledSite ) * (++marshalledUser->sites_count) )))
|
||||
return NULL;
|
||||
|
||||
marshalledUser->sites[marshalledUser->sites_count - 1] = (MPMarshalledSite){
|
||||
MPMarshalledSite *site = &marshalledUser->sites[marshalledUser->sites_count - 1];
|
||||
*site = (MPMarshalledSite){
|
||||
.name = strdup( siteName ),
|
||||
.content = NULL,
|
||||
.type = siteType,
|
||||
@ -72,7 +73,7 @@ MPMarshalledSite *mpw_marshall_site(
|
||||
.questions_count = 0,
|
||||
.questions = NULL,
|
||||
};
|
||||
return marshalledUser->sites + sizeof( MPMarshalledSite ) * (marshalledUser->sites_count - 1);
|
||||
return site;
|
||||
};
|
||||
|
||||
MPMarshalledQuestion *mpw_marshal_question(
|
||||
@ -82,10 +83,11 @@ MPMarshalledQuestion *mpw_marshal_question(
|
||||
realloc( marshalledSite->questions, sizeof( MPMarshalledQuestion ) * (++marshalledSite->questions_count) )))
|
||||
return NULL;
|
||||
|
||||
marshalledSite->questions[marshalledSite->questions_count - 1] = (MPMarshalledQuestion){
|
||||
MPMarshalledQuestion *question = &marshalledSite->questions[marshalledSite->questions_count - 1];
|
||||
*question = (MPMarshalledQuestion){
|
||||
.keyword = strdup( keyword ),
|
||||
};
|
||||
return marshalledSite->questions + sizeof( MPMarshalledSite ) * (marshalledSite->questions_count - 1);
|
||||
return question;
|
||||
}
|
||||
|
||||
bool mpw_marshal_free(
|
||||
@ -130,9 +132,9 @@ static bool mpw_marshall_write_flat(
|
||||
|
||||
mpw_string_pushf( out, "# Master Password site export\n" );
|
||||
if (user->redacted)
|
||||
mpw_string_pushf( out, "# Export of site names and passwords in clear-text.\n" );
|
||||
else
|
||||
mpw_string_pushf( out, "# Export of site names and stored passwords (unless device-private) encrypted with the master key.\n" );
|
||||
else
|
||||
mpw_string_pushf( out, "# Export of site names and passwords in clear-text.\n" );
|
||||
mpw_string_pushf( out, "# \n" );
|
||||
mpw_string_pushf( out, "##\n" );
|
||||
mpw_string_pushf( out, "# Format: %d\n", 1 );
|
||||
@ -161,6 +163,7 @@ static bool mpw_marshall_write_flat(
|
||||
|
||||
const char *content = NULL;
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site.algorithm, user->name, user->masterPassword )) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
|
||||
return false;
|
||||
@ -174,6 +177,7 @@ static bool mpw_marshall_write_flat(
|
||||
else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
|
||||
content = mpw_decrypt( masterKey, site.content, site.algorithm );
|
||||
} else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
|
||||
// Redacted
|
||||
content = strdup( site.content );
|
||||
|
||||
if (strftime( dateString, sizeof( dateString ), "%FT%TZ", gmtime( &site.lastUsed ) ))
|
||||
@ -242,6 +246,7 @@ static bool mpw_marshall_write_json(
|
||||
|
||||
const char *content = NULL;
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site.algorithm, user->name, user->masterPassword )) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
|
||||
return false;
|
||||
@ -256,6 +261,7 @@ static bool mpw_marshall_write_json(
|
||||
content = mpw_decrypt( masterKey, site.content, site.algorithm );
|
||||
}
|
||||
else if (site.type & MPSiteFeatureExportContent && site.content && strlen( site.content ))
|
||||
// Redacted
|
||||
content = strdup( site.content );
|
||||
|
||||
json_object *json_site = json_object_new_object();
|
||||
@ -284,6 +290,7 @@ static bool mpw_marshall_write_json(
|
||||
json_object_object_add( json_site_questions, question.keyword, json_site_question );
|
||||
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
MPSiteKey siteKey = mpw_siteKey( masterKey, site.name, 1, MPKeyPurposeRecovery, question.keyword, site.algorithm );
|
||||
const char *answer = mpw_sitePassword( siteKey, MPPasswordTypeGeneratedPhrase, site.algorithm );
|
||||
mpw_free( siteKey, MPSiteKeySize );
|
||||
@ -500,7 +507,8 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
site->uses = (unsigned int)atoi( str_uses );
|
||||
site->lastUsed = siteLastUsed;
|
||||
if (siteContent && strlen( siteContent )) {
|
||||
if (user->redacted) {
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
|
||||
return NULL;
|
||||
@ -509,6 +517,7 @@ static MPMarshalledUser *mpw_marshall_read_flat(
|
||||
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm );
|
||||
}
|
||||
else
|
||||
// Redacted
|
||||
site->content = strdup( siteContent );
|
||||
}
|
||||
}
|
||||
@ -653,7 +662,8 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
site->uses = siteUses;
|
||||
site->lastUsed = siteLastUsed;
|
||||
if (siteContent && strlen( siteContent )) {
|
||||
if (user->redacted) {
|
||||
if (!user->redacted) {
|
||||
// Clear Text
|
||||
if (!mpw_update_masterKey( &masterKey, &masterKeyAlgorithm, site->algorithm, fullName, masterPassword )) {
|
||||
*error = (MPMarshallError){ MPMarshallErrorInternal, "Couldn't derive master key." };
|
||||
return NULL;
|
||||
@ -662,6 +672,7 @@ static MPMarshalledUser *mpw_marshall_read_json(
|
||||
site->content = mpw_encrypt( masterKey, siteContent, site->algorithm );
|
||||
}
|
||||
else
|
||||
// Redacted
|
||||
site->content = strdup( siteContent );
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,9 @@
|
||||
#include <scrypt/sha256.h>
|
||||
#elif HAS_SODIUM
|
||||
#include "sodium.h"
|
||||
#ifdef SODIUM_LIBRARY_MINIMAL
|
||||
#include "crypto_stream_aes128ctr.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "mpw-util.h"
|
||||
@ -67,6 +70,9 @@ bool mpw_push_string(uint8_t **const buffer, size_t *const bufferSize, const cha
|
||||
|
||||
bool mpw_string_push(char **const string, const char *pushString) {
|
||||
|
||||
if (!*string)
|
||||
*string = calloc( 1, sizeof( char ) );
|
||||
|
||||
size_t stringLength = strlen( *string );
|
||||
return pushString && mpw_push_buf( (uint8_t **const)string, &stringLength, pushString, strlen( pushString ) + 1 );
|
||||
}
|
||||
@ -123,37 +129,79 @@ uint8_t const *mpw_scrypt(const size_t keySize, const char *secret, const uint8_
|
||||
mpw_free( key, keySize );
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#error No crypto support for mpw_scrypt.
|
||||
#endif
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize) {
|
||||
uint8_t const *mpw_hmac_sha256(const uint8_t *key, const size_t keySize, const uint8_t *message, const size_t messageSize) {
|
||||
|
||||
#if HAS_CPERCIVA
|
||||
uint8_t *const buffer = malloc( 32 );
|
||||
if (!buffer)
|
||||
if (!key || !keySize || !message || !messageSize)
|
||||
return NULL;
|
||||
|
||||
HMAC_SHA256_Buf( key, keySize, salt, saltSize, buffer );
|
||||
return buffer;
|
||||
#if HAS_CPERCIVA
|
||||
uint8_t *const mac = malloc( 32 );
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
HMAC_SHA256_Buf( key, keySize, message, messageSize, mac );
|
||||
#elif HAS_SODIUM
|
||||
uint8_t *const buffer = malloc( crypto_auth_hmacsha256_BYTES );
|
||||
if (!buffer)
|
||||
uint8_t *const mac = malloc( crypto_auth_hmacsha256_BYTES );
|
||||
if (!mac)
|
||||
return NULL;
|
||||
|
||||
crypto_auth_hmacsha256_state state;
|
||||
if (crypto_auth_hmacsha256_init( &state, key, keySize ) != 0 ||
|
||||
crypto_auth_hmacsha256_update( &state, salt, saltSize ) != 0 ||
|
||||
crypto_auth_hmacsha256_final( &state, buffer ) != 0) {
|
||||
mpw_free( buffer, crypto_auth_hmacsha256_BYTES );
|
||||
crypto_auth_hmacsha256_update( &state, message, messageSize ) != 0 ||
|
||||
crypto_auth_hmacsha256_final( &state, mac ) != 0) {
|
||||
mpw_free( mac, crypto_auth_hmacsha256_BYTES );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
#else
|
||||
#error No crypto support for mpw_hmac_sha256.
|
||||
#endif
|
||||
|
||||
return mac;
|
||||
}
|
||||
|
||||
static uint8_t const *mpw_aes(bool encrypt, const uint8_t *key, const size_t keySize, const uint8_t *buf, const size_t bufSize) {
|
||||
|
||||
#if HAS_SODIUM
|
||||
if (!key || keySize < crypto_stream_KEYBYTES)
|
||||
return NULL;
|
||||
|
||||
uint8_t cipherKey[crypto_stream_KEYBYTES];
|
||||
memcpy( cipherKey, key, sizeof( cipherKey ) );
|
||||
|
||||
uint8_t nonce[crypto_stream_NONCEBYTES];
|
||||
bzero( (void *)nonce, sizeof( nonce ) );
|
||||
|
||||
if (encrypt) {
|
||||
uint8_t *const cipherBuf = malloc( bufSize );
|
||||
crypto_stream_aes128ctr_xor( cipherBuf, buf, bufSize, nonce, cipherKey );
|
||||
return cipherBuf;
|
||||
} else {
|
||||
uint8_t *const plainBuf = malloc( bufSize );
|
||||
crypto_stream_aes128ctr( plainBuf, bufSize, nonce, cipherKey );
|
||||
for (size_t c = 0; c < bufSize; ++c)
|
||||
plainBuf[c] = buf[c] ^ plainBuf[c];
|
||||
return plainBuf;
|
||||
}
|
||||
#else
|
||||
#error No crypto support for mpw_aes.
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t const *mpw_aes_encrypt(const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, const size_t bufSize) {
|
||||
|
||||
return mpw_aes( true, key, keySize, plainBuf, bufSize );
|
||||
}
|
||||
|
||||
uint8_t const *mpw_aes_decrypt(const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, const size_t bufSize) {
|
||||
|
||||
return mpw_aes( false, key, keySize, cipherBuf, bufSize );
|
||||
}
|
||||
|
||||
MPKeyID mpw_id_buf(const void *buf, size_t length) {
|
||||
@ -167,6 +215,8 @@ MPKeyID mpw_id_buf(const void *buf, size_t length) {
|
||||
#elif HAS_SODIUM
|
||||
uint8_t hash[crypto_hash_sha256_BYTES];
|
||||
crypto_hash_sha256( hash, buf, length );
|
||||
#else
|
||||
#error No crypto support for mpw_id_buf.
|
||||
#endif
|
||||
|
||||
return mpw_hex( hash, sizeof( hash ) / sizeof( uint8_t ) );
|
||||
@ -325,3 +375,10 @@ const size_t mpw_utf8_strlen(const char *utf8String) {
|
||||
|
||||
return charlen;
|
||||
}
|
||||
|
||||
void printb(const void *p, size_t size) {
|
||||
|
||||
for (int i = 0; i < size; ++i)
|
||||
dbg( "%02hhX ", ((const uint8_t *)p)[i] );
|
||||
dbg( "\n" );
|
||||
}
|
||||
|
@ -121,15 +121,23 @@ bool mpw_free_string(
|
||||
|
||||
//// Cryptographic functions.
|
||||
|
||||
/** Perform a scrypt-based key derivation on the given key using the given salt and scrypt parameters.
|
||||
* @return A new keySize-size allocated buffer. */
|
||||
/** Derive a key from the given secret and salt using the scrypt KDF.
|
||||
* @return A new keySize allocated buffer containing the key. */
|
||||
uint8_t const *mpw_scrypt(
|
||||
const size_t keySize, const char *secret, const uint8_t *salt, const size_t saltSize,
|
||||
uint64_t N, uint32_t r, uint32_t p);
|
||||
/** Calculate a SHA256-based HMAC by encrypting the given salt with the given key.
|
||||
* @return A new 32-byte allocated buffer. */
|
||||
/** Calculate the MAC for the given message with the given key using SHA256-HMAC.
|
||||
* @return A new 32-byte allocated buffer containing the MAC. */
|
||||
uint8_t const *mpw_hmac_sha256(
|
||||
const uint8_t *key, const size_t keySize, const uint8_t *salt, const size_t saltSize);
|
||||
/** Encrypt a plainBuf with the given key using AES-128-CBC.
|
||||
* @return A new bufSize allocated buffer containing the cipherBuf. */
|
||||
uint8_t const *mpw_aes_encrypt(
|
||||
const uint8_t *key, const size_t keySize, const uint8_t *plainBuf, const size_t bufSize);
|
||||
/** Decrypt a cipherBuf with the given key using AES-128-CBC.
|
||||
* @return A new bufSize allocated buffer containing the plainBuf. */
|
||||
uint8_t const *mpw_aes_decrypt(
|
||||
const uint8_t *key, const size_t keySize, const uint8_t *cipherBuf, const size_t bufSize);
|
||||
|
||||
//// Visualizers.
|
||||
|
||||
@ -155,4 +163,6 @@ const char *mpw_identicon(const char *fullName, const char *masterPassword);
|
||||
/** @return The amount of display characters in the given UTF-8 string. */
|
||||
const size_t mpw_utf8_strlen(const char *utf8String);
|
||||
|
||||
void printb(const void *p, size_t size);
|
||||
|
||||
#endif // _MPW_UTIL_H
|
||||
|
@ -182,6 +182,7 @@
|
||||
DA5A09E0171A70E4005284AB /* play@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09DE171A70E4005284AB /* play@2x.png */; };
|
||||
DA5A09EA171BB0F7005284AB /* unlocked.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09E8171BB0F7005284AB /* unlocked.png */; };
|
||||
DA5A09EB171BB0F7005284AB /* unlocked@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA5A09E9171BB0F7005284AB /* unlocked@2x.png */; };
|
||||
DA5B0B401F36469400B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B3E1F36469400B663F0 /* base64.c */; };
|
||||
DA5BFA49147E415C00F98B1E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA48147E415C00F98B1E /* UIKit.framework */; };
|
||||
DA5BFA4B147E415C00F98B1E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4A147E415C00F98B1E /* Foundation.framework */; };
|
||||
DA5BFA4D147E415C00F98B1E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */; };
|
||||
@ -785,6 +786,8 @@
|
||||
DA5A09DE171A70E4005284AB /* play@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "play@2x.png"; sourceTree = "<group>"; };
|
||||
DA5A09E8171BB0F7005284AB /* unlocked.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unlocked.png; sourceTree = "<group>"; };
|
||||
DA5A09E9171BB0F7005284AB /* unlocked@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "unlocked@2x.png"; sourceTree = "<group>"; };
|
||||
DA5B0B3E1F36469400B663F0 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; };
|
||||
DA5B0B3F1F36469400B663F0 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = "<group>"; };
|
||||
DA5BFA44147E415C00F98B1E /* MasterPassword.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MasterPassword.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA48147E415C00F98B1E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
@ -1719,6 +1722,8 @@
|
||||
93D39A2239FFFE6BEC83E191 /* C */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5B0B3E1F36469400B663F0 /* base64.c */,
|
||||
DA5B0B3F1F36469400B663F0 /* base64.h */,
|
||||
93D390A99850139D0FF0211E /* mpw-algorithm_v0.c */,
|
||||
93D396F918E6470DB846C17F /* mpw-algorithm_v1.c */,
|
||||
93D390A3B351FEF1B9EDAB56 /* mpw-algorithm_v2.c */,
|
||||
@ -3905,6 +3910,7 @@
|
||||
93D392FD5E2052F7D7DB3774 /* NSString+MPMarkDown.m in Sources */,
|
||||
93D395B715D15F2B56F2A2EE /* mpw-types.c in Sources */,
|
||||
93D39943D01E70DAC3B0DF76 /* mpw-util.c in Sources */,
|
||||
DA5B0B401F36469400B663F0 /* base64.c in Sources */,
|
||||
93D39577FD8BB0945DB2F0A3 /* MPAlgorithmV3.m in Sources */,
|
||||
93D39E5F7F6D7F5C0FAD090F /* MPTypes.m in Sources */,
|
||||
DA0CC58C1EB6B030009A8ED9 /* MPGeneratedSiteEntity+CoreDataClass.m in Sources */,
|
||||
|
@ -83,6 +83,10 @@
|
||||
DA4DAE951A7D8117003E5423 /* MPTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = DA4DAE931A7D8117003E5423 /* MPTypes.m */; };
|
||||
DA5180CA19FF2F9200A587E9 /* MPAlgorithmV2.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */; };
|
||||
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */; };
|
||||
DA5B0B3A1F36467300B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
|
||||
DA5B0B3B1F36467800B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
|
||||
DA5B0B3C1F36467900B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
|
||||
DA5B0B3D1F36467900B663F0 /* base64.c in Sources */ = {isa = PBXBuildFile; fileRef = DA5B0B381F36467300B663F0 /* base64.c */; };
|
||||
DA5E5CF61724A667003798D8 /* MPAlgorithm.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C981724A667003798D8 /* MPAlgorithm.m */; };
|
||||
DA5E5CF71724A667003798D8 /* MPAlgorithmV0.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9A1724A667003798D8 /* MPAlgorithmV0.m */; };
|
||||
DA5E5CF81724A667003798D8 /* MPAlgorithmV1.m in Sources */ = {isa = PBXBuildFile; fileRef = DA5E5C9C1724A667003798D8 /* MPAlgorithmV1.m */; };
|
||||
@ -456,6 +460,8 @@
|
||||
DA5180C719FF2F9200A587E9 /* MPAlgorithmV2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAlgorithmV2.m; sourceTree = "<group>"; };
|
||||
DA5180CC19FF307E00A587E9 /* MPAppDelegate_Store.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPAppDelegate_Store.h; sourceTree = "<group>"; };
|
||||
DA5180CD19FF307E00A587E9 /* MPAppDelegate_Store.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPAppDelegate_Store.m; sourceTree = "<group>"; };
|
||||
DA5B0B381F36467300B663F0 /* base64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = base64.c; sourceTree = "<group>"; };
|
||||
DA5B0B391F36467300B663F0 /* base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = base64.h; sourceTree = "<group>"; };
|
||||
DA5BFA44147E415C00F98B1E /* Master Password.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Master Password.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
DA5BFA4A147E415C00F98B1E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||
DA5BFA4C147E415C00F98B1E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||
@ -1809,6 +1815,8 @@
|
||||
DA6773291A4746AF004F356A /* C */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DA5B0B381F36467300B663F0 /* base64.c */,
|
||||
DA5B0B391F36467300B663F0 /* base64.h */,
|
||||
DA1C7AB71F1A8F6E009A3551 /* cli */,
|
||||
DA831A271A6E1146000AC234 /* mpw-algorithm_v0.c */,
|
||||
DA831A281A6E1146000AC234 /* mpw-algorithm_v1.c */,
|
||||
@ -2528,6 +2536,7 @@
|
||||
files = (
|
||||
DA1C7AAA1F1A8F24009A3551 /* mpw-marshall.c in Sources */,
|
||||
DA1C7AAB1F1A8F24009A3551 /* mpw-types.c in Sources */,
|
||||
DA5B0B3D1F36467900B663F0 /* base64.c in Sources */,
|
||||
DA1C7AAC1F1A8F24009A3551 /* mpw-util.c in Sources */,
|
||||
DA1C7AC31F1A8FBA009A3551 /* mpw-cli.c in Sources */,
|
||||
DA7471A31F2B71AE005F3468 /* mpw-marshall-util.c in Sources */,
|
||||
@ -2539,6 +2548,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
DA5B0B3C1F36467900B663F0 /* base64.c in Sources */,
|
||||
DA1C7ACA1F1A8FD8009A3551 /* mpw-types.c in Sources */,
|
||||
DA1C7ACB1F1A8FD8009A3551 /* mpw-util.c in Sources */,
|
||||
DA1C7AD71F1A8FE6009A3551 /* mpw-bench.c in Sources */,
|
||||
@ -2566,6 +2576,7 @@
|
||||
DA5180CE19FF307E00A587E9 /* MPAppDelegate_Store.m in Sources */,
|
||||
DA5E5CFA1724A667003798D8 /* MPAppDelegate_Shared.m in Sources */,
|
||||
DA5E5CFC1724A667003798D8 /* MPConfig.m in Sources */,
|
||||
DA5B0B3A1F36467300B663F0 /* base64.c in Sources */,
|
||||
DA26861F1EBFD7A40001E37E /* MPSiteEntity+CoreDataClass.m in Sources */,
|
||||
DA3B8456190FC89700246EEA /* MPFixable.m in Sources */,
|
||||
DA5E5D001724A667003798D8 /* MPEntities.m in Sources */,
|
||||
@ -2602,6 +2613,7 @@
|
||||
DA6774451A474A3B004F356A /* mpw-types.c in Sources */,
|
||||
DA6774461A474A3B004F356A /* mpw-util.c in Sources */,
|
||||
DA1C7AD91F1A8FF4009A3551 /* mpw-tests.c in Sources */,
|
||||
DA5B0B3B1F36467800B663F0 /* base64.c in Sources */,
|
||||
DA6774431A474A3B004F356A /* mpw-algorithm.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -259,12 +259,13 @@ mpw() {
|
||||
(( mpw_color )) && CFLAGS+=( -DMPW_COLOR ) LDFLAGS+=( -l"curses" )
|
||||
(( mpw_json )) && CFLAGS+=( -DMPW_JSON ) LDFLAGS+=( -l"json-c" )
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-marshall-util.c -o core/mpw-marshall-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-marshall.c -o core/mpw-marshall.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall-util.o" "core/mpw-marshall.o" \
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" "core/mpw-marshall-util.o" "core/mpw-marshall.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-cli.c" -o "mpw"
|
||||
echo "done! Now run ./install or use ./mpw"
|
||||
}
|
||||
@ -299,10 +300,11 @@ mpw-bench() {
|
||||
-l"crypto"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-bench.c" -o "mpw-bench"
|
||||
echo "done! Now use ./mpw-bench"
|
||||
}
|
||||
@ -331,11 +333,12 @@ mpw-tests() {
|
||||
-l"crypto" -l"xml2"
|
||||
)
|
||||
|
||||
cc "${CFLAGS[@]}" "$@" -c core/base64.c -o core/base64.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-algorithm.c -o core/mpw-algorithm.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-types.c -o core/mpw-types.o
|
||||
cc "${CFLAGS[@]}" "$@" -c core/mpw-util.c -o core/mpw-util.o
|
||||
cc "${CFLAGS[@]}" "$@" -c cli/mpw-tests-util.c -o cli/mpw-tests-util.o
|
||||
cc "${CFLAGS[@]}" "$@" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
cc "${CFLAGS[@]}" "$@" "core/base64.o" "core/mpw-algorithm.o" "core/mpw-types.o" "core/mpw-util.o" \
|
||||
"${LDFLAGS[@]}" "cli/mpw-tests-util.o" "cli/mpw-tests.c" -o "mpw-tests"
|
||||
echo "done! Now use ./mpw-tests"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user