merged in default

doxygen-key-id
commit 591c699e40

@ -71,6 +71,8 @@ IF %ERRORLEVEL% NEQ 0 (
DEL *-sample.c
CD %pwd%\..
IF NOT EXIST pEp mklink /d pEp pEpEngine\src
RD /S/Q pEp
MKDIR pEp
XCOPY pEpEngine\src\*.h pEp\ /Y/F/I
POPD

@ -90,13 +90,140 @@
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\asn.1\*.h" />
<None Include="..\generate_code.cmd" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\asn.1\*.c" />
<ClCompile Include="..\..\asn.1\asn_codecs_prim.c" />
<ClCompile Include="..\..\asn.1\asn_SEQUENCE_OF.c" />
<ClCompile Include="..\..\asn.1\asn_SET_OF.c" />
<ClCompile Include="..\..\asn.1\Beacon.c" />
<ClCompile Include="..\..\asn.1\ber_decoder.c" />
<ClCompile Include="..\..\asn.1\ber_tlv_length.c" />
<ClCompile Include="..\..\asn.1\ber_tlv_tag.c" />
<ClCompile Include="..\..\asn.1\BIT_STRING.c" />
<ClCompile Include="..\..\asn.1\BOOLEAN.c" />
<ClCompile Include="..\..\asn.1\Command.c" />
<ClCompile Include="..\..\asn.1\Commands.c" />
<ClCompile Include="..\..\asn.1\CommitAccept.c" />
<ClCompile Include="..\..\asn.1\CommitAcceptForGroup.c" />
<ClCompile Include="..\..\asn.1\CommitAcceptOfferer.c" />
<ClCompile Include="..\..\asn.1\CommitAcceptRequester.c" />
<ClCompile Include="..\..\asn.1\CommitReject.c" />
<ClCompile Include="..\..\asn.1\constraints.c" />
<ClCompile Include="..\..\asn.1\constr_CHOICE.c" />
<ClCompile Include="..\..\asn.1\constr_SEQUENCE.c" />
<ClCompile Include="..\..\asn.1\constr_SEQUENCE_OF.c" />
<ClCompile Include="..\..\asn.1\constr_SET_OF.c" />
<ClCompile Include="..\..\asn.1\constr_TYPE.c" />
<ClCompile Include="..\..\asn.1\der_encoder.c" />
<ClCompile Include="..\..\asn.1\Distribution.c" />
<ClCompile Include="..\..\asn.1\ElectGroupKeyResetLeader.c" />
<ClCompile Include="..\..\asn.1\GroupHandshake.c" />
<ClCompile Include="..\..\asn.1\GroupKeysAndClose.c" />
<ClCompile Include="..\..\asn.1\GroupKeysForNewMember.c" />
<ClCompile Include="..\..\asn.1\GroupKeysUpdate.c" />
<ClCompile Include="..\..\asn.1\GroupTrustThisKey.c" />
<ClCompile Include="..\..\asn.1\Hash.c" />
<ClCompile Include="..\..\asn.1\Hex.c" />
<ClCompile Include="..\..\asn.1\Identity.c" />
<ClCompile Include="..\..\asn.1\IdentityList.c" />
<ClCompile Include="..\..\asn.1\InitUnledGroupKeyReset.c" />
<ClCompile Include="..\..\asn.1\INTEGER.c" />
<ClCompile Include="..\..\asn.1\ISO639-1.c" />
<ClCompile Include="..\..\asn.1\KeyReset.c" />
<ClCompile Include="..\..\asn.1\KeySync.c" />
<ClCompile Include="..\..\asn.1\NativeEnumerated.c" />
<ClCompile Include="..\..\asn.1\NativeInteger.c" />
<ClCompile Include="..\..\asn.1\NegotiationOpen.c" />
<ClCompile Include="..\..\asn.1\NegotiationRequest.c" />
<ClCompile Include="..\..\asn.1\NegotiationRequestGrouped.c" />
<ClCompile Include="..\..\asn.1\OCTET_STRING.c" />
<ClCompile Include="..\..\asn.1\OwnKeysOfferer.c" />
<ClCompile Include="..\..\asn.1\OwnKeysRequester.c" />
<ClCompile Include="..\..\asn.1\pdu_collection.c" />
<ClCompile Include="..\..\asn.1\per_decoder.c" />
<ClCompile Include="..\..\asn.1\per_encoder.c" />
<ClCompile Include="..\..\asn.1\per_opentype.c" />
<ClCompile Include="..\..\asn.1\per_support.c" />
<ClCompile Include="..\..\asn.1\PrintableString.c" />
<ClCompile Include="..\..\asn.1\PString.c" />
<ClCompile Include="..\..\asn.1\Rollback.c" />
<ClCompile Include="..\..\asn.1\Sync.c" />
<ClCompile Include="..\..\asn.1\SynchronizeGroupKeys.c" />
<ClCompile Include="..\..\asn.1\TID.c" />
<ClCompile Include="..\..\asn.1\UTF8String.c" />
<ClCompile Include="..\..\asn.1\Version.c" />
<ClCompile Include="..\..\asn.1\xer_decoder.c" />
<ClCompile Include="..\..\asn.1\xer_encoder.c" />
<ClCompile Include="..\..\asn.1\xer_support.c" />
</ItemGroup>
<ItemGroup>
<None Include="..\generate_code.cmd" />
<ClInclude Include="..\..\asn.1\asn_application.h" />
<ClInclude Include="..\..\asn.1\asn_codecs.h" />
<ClInclude Include="..\..\asn.1\asn_codecs_prim.h" />
<ClInclude Include="..\..\asn.1\asn_internal.h" />
<ClInclude Include="..\..\asn.1\asn_SEQUENCE_OF.h" />
<ClInclude Include="..\..\asn.1\asn_SET_OF.h" />
<ClInclude Include="..\..\asn.1\asn_system.h" />
<ClInclude Include="..\..\asn.1\Beacon.h" />
<ClInclude Include="..\..\asn.1\ber_decoder.h" />
<ClInclude Include="..\..\asn.1\ber_tlv_length.h" />
<ClInclude Include="..\..\asn.1\ber_tlv_tag.h" />
<ClInclude Include="..\..\asn.1\BIT_STRING.h" />
<ClInclude Include="..\..\asn.1\BOOLEAN.h" />
<ClInclude Include="..\..\asn.1\Command.h" />
<ClInclude Include="..\..\asn.1\Commands.h" />
<ClInclude Include="..\..\asn.1\CommitAccept.h" />
<ClInclude Include="..\..\asn.1\CommitAcceptForGroup.h" />
<ClInclude Include="..\..\asn.1\CommitAcceptOfferer.h" />
<ClInclude Include="..\..\asn.1\CommitAcceptRequester.h" />
<ClInclude Include="..\..\asn.1\CommitReject.h" />
<ClInclude Include="..\..\asn.1\constraints.h" />
<ClInclude Include="..\..\asn.1\constr_CHOICE.h" />
<ClInclude Include="..\..\asn.1\constr_SEQUENCE.h" />
<ClInclude Include="..\..\asn.1\constr_SEQUENCE_OF.h" />
<ClInclude Include="..\..\asn.1\constr_SET_OF.h" />
<ClInclude Include="..\..\asn.1\constr_TYPE.h" />
<ClInclude Include="..\..\asn.1\der_encoder.h" />
<ClInclude Include="..\..\asn.1\Distribution.h" />
<ClInclude Include="..\..\asn.1\ElectGroupKeyResetLeader.h" />
<ClInclude Include="..\..\asn.1\GroupHandshake.h" />
<ClInclude Include="..\..\asn.1\GroupKeysAndClose.h" />
<ClInclude Include="..\..\asn.1\GroupKeysForNewMember.h" />
<ClInclude Include="..\..\asn.1\GroupKeysUpdate.h" />
<ClInclude Include="..\..\asn.1\GroupTrustThisKey.h" />
<ClInclude Include="..\..\asn.1\Hash.h" />
<ClInclude Include="..\..\asn.1\Hex.h" />
<ClInclude Include="..\..\asn.1\Identity.h" />
<ClInclude Include="..\..\asn.1\IdentityList.h" />
<ClInclude Include="..\..\asn.1\InitUnledGroupKeyReset.h" />
<ClInclude Include="..\..\asn.1\INTEGER.h" />
<ClInclude Include="..\..\asn.1\ISO639-1.h" />
<ClInclude Include="..\..\asn.1\KeyReset.h" />
<ClInclude Include="..\..\asn.1\KeySync.h" />
<ClInclude Include="..\..\asn.1\NativeEnumerated.h" />
<ClInclude Include="..\..\asn.1\NativeInteger.h" />
<ClInclude Include="..\..\asn.1\NegotiationOpen.h" />
<ClInclude Include="..\..\asn.1\NegotiationRequest.h" />
<ClInclude Include="..\..\asn.1\NegotiationRequestGrouped.h" />
<ClInclude Include="..\..\asn.1\OCTET_STRING.h" />
<ClInclude Include="..\..\asn.1\OwnKeysOfferer.h" />
<ClInclude Include="..\..\asn.1\OwnKeysRequester.h" />
<ClInclude Include="..\..\asn.1\per_decoder.h" />
<ClInclude Include="..\..\asn.1\per_encoder.h" />
<ClInclude Include="..\..\asn.1\per_opentype.h" />
<ClInclude Include="..\..\asn.1\per_support.h" />
<ClInclude Include="..\..\asn.1\PrintableString.h" />
<ClInclude Include="..\..\asn.1\PString.h" />
<ClInclude Include="..\..\asn.1\Rollback.h" />
<ClInclude Include="..\..\asn.1\Sync.h" />
<ClInclude Include="..\..\asn.1\SynchronizeGroupKeys.h" />
<ClInclude Include="..\..\asn.1\TID.h" />
<ClInclude Include="..\..\asn.1\UTF8String.h" />
<ClInclude Include="..\..\asn.1\Version.h" />
<ClInclude Include="..\..\asn.1\xer_decoder.h" />
<ClInclude Include="..\..\asn.1\xer_encoder.h" />
<ClInclude Include="..\..\asn.1\xer_support.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />

File diff suppressed because it is too large Load Diff

@ -224,6 +224,9 @@
<Project>{9a67164d-b8f8-4601-a24b-28afe774d41c}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="generate_code.cmd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets" />
</Project>

@ -276,4 +276,9 @@
<ItemGroup>
<Text Include="..\LICENSE.txt" />
</ItemGroup>
<ItemGroup>
<None Include="generate_code.cmd">
<Filter>Quelldateien</Filter>
</None>
</ItemGroup>
</Project>

@ -0,0 +1,218 @@
import subprocess
import re
import sys
import argparse
parser = argparse.ArgumentParser(description='Automate the RC release process as sanely as possible.')
parser.add_argument('-r','--rev',nargs=1, help="revision number or changeset to tag as next RC")
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument('-v','--version',nargs=4, type=int, help="force this version - bypasses version inference. Format: major minor patch RC")
group.add_argument('--rc', type=int, help="force this RC number on the inferred version")
args = parser.parse_args()
# Note: we could get this from the macros, but since folks seem to be actually upgrading
# the release tag manually correctly and not the macro, let's just check both
cmd = ["hg", "log", "-r", ".", "--template", "\"{latesttag(r're:Release_[0-9]+\.[0-9]+\.[0-9]+-RC[0-9]+')}\""]
result = subprocess.run(cmd, capture_output=True)
release_string = result.stdout.decode("utf-8").replace('"','')
#print(release_string)
changeset = args.rev # can be None :)
major = -1
minor = -1
patch = -1
rc = -1
if args.version:
major = args.version[0]
minor = args.version[1]
patch = args.version[2]
rc = args.version[3]
#print(rc)
if (major < 0) or (minor < 0) or (patch < 0) or (rc < 0):
raise Exception("Version numbers must all be positive values.")
elif args.rc:
rc = args.rc
if (rc < 0):
raise Exception("RC numbers must all be positive values.")
#define PEP_ENGINE_VERSION_MAJOR 2
#define PEP_ENGINE_VERSION_MINOR 1
#define PEP_ENGINE_VERSION_PATCH 0
#define PEP_ENGINE_VERSION_RC 13
# Amateur hour. Biteme.
cmd = ["grep", "-E", "#define PEP_ENGINE_VERSION_[A-Z]+[ \t]+[0-9]+", "src/pEpEngine.h"]
result = subprocess.run(cmd, capture_output=True)
grep_output = result.stdout.decode("utf-8")
#print(grep_output)
if not args.version:
src_nums = []
src_nums = re.findall(r'([0-9]+)', grep_output)
if not src_nums:
raise Exception("Somehow, the source values for the engine versions were not found in src/pEpEngine.h. Aborting.")
if len(src_nums) != 4:
raise Exception("Somehow, we could not extract all version numbers from the header file src/pEpEngine.h. Aborting.")
tag_nums = []
if release_string.startswith("Release_"):
tag_nums = re.findall(r'([0-9]+)', release_string)
# for num in tagnums:
# print (num)
if not tag_nums or len(tag_nums) != 4:
if not tag_nums:
print("Wow... there is no extant release tag. What did you do, wipe the repository?")
else:
print("Somehow, there was an error with the numbering of the tag \"" + release_string + "\"")
print("Do you want to continue? We'll make a tag from the source RC info. (Y/N)[enter]")
a = input().lower()
if not (a.startswith("y") or a.startswith("Y")):
sys.exit()
force = False
if len(tag_nums) == 4 and src_nums:
major_tag = int(tag_nums[0])
major_src = int(src_nums[0])
minor_tag = int(tag_nums[1])
minor_src = int(src_nums[1])
patch_tag = int(tag_nums[2])
patch_src = int(src_nums[2])
rc_tag = int(tag_nums[3])
rc_src = int(src_nums[3])
print("Inferring current/next version info for automatic upgrade:")
print("Tagged (should show current): " + str(major_tag) + "." + str(minor_tag) + "." + str(patch_tag) + "." + str(rc_tag))
print("Source (should show *next* (i.e. this upgrade)): " + str(major_src) + "." + str(minor_src) + "." + str(patch_src) + "." + str(rc_src))
if (major_tag == major_src):
major = major_tag
if (minor_tag == minor_src):
minor = minor_tag
if (patch_tag == patch_src):
patch = patch_tag
# Hoorah, we're just changing the RC number.
if (rc < 0):
if (rc_tag == (rc_src - 1)):
# Best case!
rc = rc_src
elif (rc_tag == rc_src):
print("Someone was naughty and didn't bump the RC number in the src, or you made a mistake you want to fix.")
print("Current tagged version is " + str(major) + "." + str(minor) + "." + str(patch) + " RC" + rc_tag + ".")
print("(I)ncrement,(F)orce same version,(A)bort? [enter]")
a = input().lower()
a = lower(a)
if (a.startswith(i)):
rc = rc_tag + 1
elif (a.startswith(f)):
rc = rc_tag
force = True
else:
print("Aborting...")
sys.exit()
else:
print("RC numbers are messed up. The last tagged version is " + str(rc_tag) + ", while the last source version is " + str(rc_src) + ".")
print("Please enter the RC version you want to use, followed by enter:")
a = input().lower()
rc = int(a) # Will raise value error if not a number. User deserves it, frankly.
#Ok, we now have a value. Good.
# This feels extremely suboptimal, but I'm tired and don't care
if (rc < 0):
if (major < 0):
if (major_src == major_tag + 1) and (minor_src == 0) and (patch_src == 0):
major = major_src
minor = 0
patch = 0
else:
print("Tagged release major version and source versions are too different for automatic deduction. Please do this manually.")
sys.exit()
elif (minor < 0):
if (minor_src == minor_tag + 1) and (patch_src == 0):
minor = minor_src
patch = 0
else:
print("Tagged release major version and source versions are too different for automatic deduction. Please do this manually.")
sys.exit()
elif (patch_src == patch_tag + 1):
patch = patch_src
else:
print("Tagged release major version and source versions are too different for automatic deduction. Please do this manually.")
sys.exit()
# if we got this far, it was a version upgrade.
if (rc_src > 0):
print("We detected a version upgrade, but the source indicates the next RC is RC " + str(rc_src))
print("(K)eep,(R)eset to 0,(A)bort? [enter]")
a = input().lower()
if a.startswith("k"):
rc = rc_src
elif a.startswith("r"):
rc = 0
else:
print("Aborting...")
else:
rc = 0
# Ok, so now, after all that, we should have the right version numbers.
# If there's no changeset to tag, we take the latest local default
if not changeset:
cmd = ["hg", "id", "-i", "-r", "default"]
result = subprocess.run(cmd, capture_output=True)
changeset = result.stdout.decode("utf-8").replace('"','').replace('\n','')
if not changeset:
raise Exception("Unable to determine latest default changeset. Aborting.")
rev_tag = "Release_" + str(major) + "." + str(minor) + "." + str(patch) + "-RC" + str(rc)
print("Preparing to tag changeset " + changeset + " with tag " + rev_tag + ".\n\nProceed? (Y/N) [enter]")
a = input().lower()
if not (a.startswith("y")):
sys.exit()
cmd = ["hg", "tag", "-r", changeset, rev_tag]
subprocess.run(cmd, check=True, capture_output=False)
if not grep_output:
print("Information: Not writing version/RC info to src/pEpEngine.h")
sys.exit()
# If successful, then bump the RC
with open('src/pEpEngine.h', 'r') as file :
filedata = file.read()
grep_strs = grep_output.split("\n")
cmd = ["grep", "-E", "#define PEP_ENGINE_VERSION[ \t]+\"[0-9]+.[0-9]+.[0-9]+\"", "src/pEpEngine.h"]
result = subprocess.run(cmd, capture_output=True)
grep_output = result.stdout.decode("utf-8")
#define PEP_ENGINE_VERSION "2.1.0"
version_str = str(major) + "." + str(minor) + "." + str(patch)
filedata = filedata.replace(grep_output, "#define PEP_ENGINE_VERSION \"" + version_str + "\"\n")
filedata = filedata.replace(grep_strs[0], "#define PEP_ENGINE_VERSION_MAJOR " + str(major))
filedata = filedata.replace(grep_strs[1], "#define PEP_ENGINE_VERSION_MINOR " + str(minor))
filedata = filedata.replace(grep_strs[2], "#define PEP_ENGINE_VERSION_PATCH " + str(patch))
filedata = filedata.replace(grep_strs[3], "#define PEP_ENGINE_VERSION_RC " + str(rc + 1))
# Write the file out again
with open('src/pEpEngine.h', 'w') as file:
file.write(filedata)
comment = "Automatically bumped RC in source for future release. Next RC after this one will be " + version_str + "-RC" + str(rc + 1) + " **if released**."
#print("about to run with this comment:")
print(comment)
cmd = ["hg", "commit", "-m", comment]
subprocess.run(cmd, capture_output=False)
print("New engine release: " + rev_tag + " Changeset: " + changeset)

@ -247,34 +247,40 @@ PEP_STATUS try_base_prepare_message(
// https://dev.pep.foundation/Engine/MessageToSendPassphrase
if (session->curr_passphrase) {
// first try with empty passphrase
char *passphrase = session->curr_passphrase;
session->curr_passphrase = NULL;
// first try with empty passphrase
char *passphrase = session->curr_passphrase;
session->curr_passphrase = NULL;
status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
session->curr_passphrase = passphrase;
if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
return status;
if (!EMPTYSTR(session->curr_passphrase)) {
// try configured passphrase
status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
session->curr_passphrase = passphrase;
if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
return status;
}
do {
// then try passphrases
status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
// then try passphrases from the cache
status = session->messageToSend(NULL);
// if there will be no passphrase then exit
if (status == PEP_SYNC_NO_CHANNEL)
break;
// if a passphrase is needed ask the app
if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
status = session->messageToSend(NULL);
if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
pEp_identity *_me = identity_dup(me);
if (!_me)
return PEP_OUT_OF_MEMORY;
session->notifyHandshake(_me, NULL, SYNC_PASSPHRASE_REQUIRED);
break;
}
pEp_identity* _me = identity_dup(me);
if (!_me)
return PEP_OUT_OF_MEMORY;
session->notifyHandshake(_me, NULL, SYNC_PASSPHRASE_REQUIRED);
}
else {
break;
else if (status == PEP_STATUS_OK) {
status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
}
} while (!status);
} while (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE);
return status;
}

@ -731,7 +731,7 @@ PEP_STATUS create_standalone_key_reset_message(PEP_SESSION session,
message* output_msg = NULL;
status = encrypt_message(session, reset_msg, NULL,
&output_msg, PEP_enc_PGP_MIME,
&output_msg, PEP_enc_auto,
PEP_encrypt_flag_key_reset_only);
if (status == PEP_STATUS_OK)
@ -977,7 +977,7 @@ static PEP_STATUS _key_reset_device_group_for_shared_key(PEP_SESSION session,
// encrypt this baby and get out
// extra keys???
status = encrypt_message(session, outmsg, NULL, &enc_msg, PEP_enc_PGP_MIME, PEP_encrypt_flag_key_reset_only);
status = encrypt_message(session, outmsg, NULL, &enc_msg, PEP_enc_auto, PEP_encrypt_flag_key_reset_only);
if (status != PEP_STATUS_OK) {
goto pEp_free;

@ -577,6 +577,7 @@ static PEP_STATUS prepare_updated_identity(PEP_SESSION session,
}
transfer_ident_lang_and_flags(return_id, stored_ident);
return_id->enc_format = stored_ident->enc_format;
if (return_id->comm_type == PEP_ct_unknown)
return_id->comm_type = PEP_ct_key_not_found;
@ -2127,4 +2128,3 @@ PEP_STATUS clean_own_key_defaults(PEP_SESSION session) {
}
return status;
}

@ -31,17 +31,6 @@ typedef enum _PEP_msg_direction {
PEP_dir_outgoing
} PEP_msg_direction;
typedef enum _PEP_enc_format {
PEP_enc_none = 0, // message is not encrypted
PEP_enc_pieces = 1, // inline PGP + PGP extensions, was removed
PEP_enc_inline = 1, // still there
PEP_enc_S_MIME, // RFC5751
PEP_enc_PGP_MIME, // RFC3156
PEP_enc_PEP, // pEp encryption format
PEP_enc_PGP_MIME_Outlook1, // Message B0rken by Outlook type 1
PEP_enc_inline_EA
} PEP_enc_format;
struct _message_ref_list;
typedef struct _message {

@ -6,6 +6,7 @@
#include "pEp_internal.h"
#include "message_api.h"
#include "pEpEngine.h"
#include "platform.h"
#include "mime.h"
@ -301,8 +302,18 @@ static char * combine_short_and_long(const char *shortmsg, const char *longmsg)
assert(shortmsg);
unsigned char pEpstr[] = PEP_SUBJ_STRING;
assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) != 0);
// assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) != 0);
// in case encrypt_message() is called twice with a different passphrase this was done already
if (strcmp(shortmsg, "pEp") == 0 || _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
char *ptext = strdup(longmsg);
assert(ptext);
if (!ptext)
return NULL;
return ptext;
}
if (!shortmsg || strcmp(shortmsg, "pEp") == 0 ||
_unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
if (!longmsg) {
@ -1746,6 +1757,60 @@ static void _cleanup_src(message* src, bool remove_attached_key) {
}
}
static PEP_STATUS id_list_set_enc_format(PEP_SESSION session, identity_list* id_list, PEP_enc_format enc_format) {
PEP_STATUS status = PEP_STATUS_OK;
identity_list* id_list_curr = id_list;
for ( ; id_list_curr && id_list_curr->ident && status == PEP_STATUS_OK; id_list_curr = id_list_curr->next) {
status = set_ident_enc_format(session, id_list_curr->ident, enc_format);
}
return status;
}
// N.B.
// depends on update_identity and friends having already been called on list
static void update_encryption_format(identity_list* id_list, PEP_enc_format* enc_format) {
identity_list* id_list_curr;
for (id_list_curr = id_list; id_list_curr && id_list_curr->ident; id_list_curr = id_list_curr->next) {
PEP_enc_format format = id_list_curr->ident->enc_format;
if (format != PEP_enc_none) {
*enc_format = format;
break;
}
}
}
PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr)
{
assert(session);
if (!session)
return PEP_ILLEGAL_VALUE;
if (EMPTYSTR(fpr))
return PEP_KEY_NOT_FOUND;
stringlist_t *keylist = new_stringlist(fpr);
if (!keylist)
return PEP_OUT_OF_MEMORY;
char *ctext = NULL;
size_t csize = 0;
PEP_STATUS status = encrypt_and_sign(session, keylist, "pEp", 4, &ctext, &csize);
free(ctext);
return status;
}
static bool failed_test(PEP_STATUS status)
{
if (status == PEP_OUT_OF_MEMORY ||
status == PEP_PASSPHRASE_REQUIRED ||
status == PEP_WRONG_PASSPHRASE ||
status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
return true;
return false;
}
DYNAMIC_API PEP_STATUS encrypt_message(
PEP_SESSION session,
message *src,
@ -1794,6 +1859,11 @@ DYNAMIC_API PEP_STATUS encrypt_message(
if (status != PEP_STATUS_OK)
goto pEp_error;
// is a passphrase needed?
status = probe_encrypt(session, src->from->fpr);
if (failed_test(status))
return status;
char* send_fpr = strdup(src->from->fpr ? src->from->fpr : "");
src->_sender_fpr = send_fpr;
@ -2006,6 +2076,23 @@ DYNAMIC_API PEP_STATUS encrypt_message(
if (max_version_major == 1)
force_v_1 = true;
if (enc_format == PEP_enc_auto) {
update_encryption_format(src->to, &enc_format);
if (enc_format == PEP_enc_auto && src->cc)
update_encryption_format(src->cc, &enc_format);
if (enc_format == PEP_enc_auto && src->bcc)
update_encryption_format(src->bcc, &enc_format);
if (enc_format == PEP_enc_auto)
enc_format = PEP_enc_PEP;
}
else if (enc_format != PEP_enc_none) {
status = id_list_set_enc_format(session, src->to, enc_format);
status = ((status != PEP_STATUS_OK || !(src->cc)) ? status : id_list_set_enc_format(session, src->cc, enc_format));
status = ((status != PEP_STATUS_OK || !(src->bcc)) ? status : id_list_set_enc_format(session, src->bcc, enc_format));
if (status != PEP_STATUS_OK)
goto pEp_error;
}
if (enc_format == PEP_enc_none || !dest_keys_found ||
stringlist_length(keys) == 0 ||
@ -2186,6 +2273,11 @@ DYNAMIC_API PEP_STATUS encrypt_message_and_add_priv_key(
if (status != PEP_STATUS_OK)
goto pEp_free;
// is a passphrase needed?
status = probe_encrypt(session, own_identity->fpr);
if (failed_test(status))
goto pEp_free;
// Ok, now we know the address is an own address. All good. Then...
own_private_fpr = own_identity->fpr;
own_identity->fpr = strdup(to_fpr);
@ -2368,6 +2460,11 @@ DYNAMIC_API PEP_STATUS encrypt_message_for_self(
if (!target_fpr)
return PEP_KEY_NOT_FOUND; // FIXME: Error condition
// is a passphrase needed?
status = probe_encrypt(session, target_fpr);
if (failed_test(status))
return status;
keys = new_stringlist(target_fpr);
stringlist_t *_k = keys;
@ -3725,6 +3822,11 @@ static PEP_STATUS _decrypt_message(
pull_up_attached_main_msg(src);
if (imported_key_fprs)
*imported_key_fprs = _imported_key_list;
if (changed_public_keys)
*changed_public_keys = _changed_keys;
return PEP_UNENCRYPTED;
}
@ -5345,34 +5447,40 @@ PEP_STATUS try_encrypt_message(
// https://dev.pep.foundation/Engine/MessageToSendPassphrase
if (session->curr_passphrase) {
// first try with empty passphrase
char *passphrase = session->curr_passphrase;
session->curr_passphrase = NULL;
// first try with empty passphrase
char* passphrase = session->curr_passphrase;
session->curr_passphrase = NULL;
status = encrypt_message(session, src, extra, dst, enc_format, flags);
session->curr_passphrase = passphrase;
if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
return status;
if (!EMPTYSTR(session->curr_passphrase)) {
// try configured passphrase
status = encrypt_message(session, src, extra, dst, enc_format, flags);
session->curr_passphrase = passphrase;
if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
return status;
}
do {
// then try passphrases
status = encrypt_message(session, src, extra, dst, enc_format, flags);
// then try passphrases from the cache
status = session->messageToSend(NULL);
// if there will be no passphrase then exit
if (status == PEP_SYNC_NO_CHANNEL)
break;
// if a passphrase is needed ask the app
if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
status = session->messageToSend(NULL);
if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
pEp_identity *me = identity_dup(src->from);
if (!me)
return PEP_OUT_OF_MEMORY;
session->notifyHandshake(me, NULL, SYNC_PASSPHRASE_REQUIRED);
break;
}
pEp_identity* _me = identity_dup(src->from);
if (!_me)
return PEP_OUT_OF_MEMORY;
session->notifyHandshake(_me, NULL, SYNC_PASSPHRASE_REQUIRED);
}
else {
break;
else if (status == PEP_STATUS_OK) {
status = encrypt_message(session, src, extra, dst, enc_format, flags);
}
} while (!status);
} while (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE);
return status;
}

@ -85,7 +85,7 @@ static const char *sql_trustword =
static const char *sql_get_identity =
"select identity.main_key_id, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
" is_own, pEp_version_major, pEp_version_minor"
" is_own, pEp_version_major, pEp_version_minor, enc_format"
" from identity"
" join person on id = identity.user_id"
" left join pgp_keypair on fpr = identity.main_key_id"
@ -103,7 +103,7 @@ static const char *sql_get_identity =
static const char *sql_get_identities_by_main_key_id =
"select address, identity.user_id, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
" is_own, pEp_version_major, pEp_version_minor"
" is_own, pEp_version_major, pEp_version_minor, enc_format"
" from identity"
" join person on id = identity.user_id"
" left join pgp_keypair on fpr = identity.main_key_id"
@ -115,7 +115,7 @@ static const char *sql_get_identities_by_main_key_id =
static const char *sql_get_identity_without_trust_check =
"select identity.main_key_id, username, lang,"
" identity.flags, is_own, pEp_version_major, pEp_version_minor"
" identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format"
" from identity"
" join person on id = identity.user_id"
" where (case when (address = ?1) then (1)"
@ -129,7 +129,7 @@ static const char *sql_get_identity_without_trust_check =
static const char *sql_get_identities_by_address =
"select user_id, identity.main_key_id, username, lang,"
" identity.flags, is_own, pEp_version_major, pEp_version_minor"
" identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format"
" from identity"
" join person on id = identity.user_id"
" where (case when (address = ?1) then (1)"
@ -143,7 +143,7 @@ static const char *sql_get_identities_by_address =
static const char *sql_get_identities_by_userid =
"select address, identity.main_key_id, username, comm_type, lang,"
" identity.flags | pgp_keypair.flags,"
" is_own, pEp_version_major, pEp_version_minor"
" is_own, pEp_version_major, pEp_version_minor, enc_format"
" from identity"
" join person on id = identity.user_id"
" left join pgp_keypair on fpr = identity.main_key_id"
@ -315,6 +315,16 @@ static const char *sql_unset_identity_flags =
" end) = 1"
" and user_id = ?3 ;";
static const char *sql_set_ident_enc_format =
"update identity "
" set enc_format = ?1 "
" where (case when (address = ?2) then (1)"
" when (lower(address) = lower(?2)) then (1)"
" when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) "
" else 0 "
" end) = 1 "
" and user_id = ?3 ;";
static const char *sql_set_pEp_version =
"update identity "
" set pEp_version_major = ?1, "
@ -1061,7 +1071,7 @@ DYNAMIC_API PEP_STATUS init(
sqlite3_busy_timeout(_session->system_db, 1000);
// increment this when patching DDL
#define _DDL_USER_VERSION "13"
#define _DDL_USER_VERSION "14"
if (in_first) {
@ -1123,7 +1133,8 @@ DYNAMIC_API PEP_STATUS init(
" flags integer default 0,\n"
" is_own integer default 0,\n"
" pEp_version_major integer default 0,\n"
" pEp_version_minor integer default 0,\n"
" pEp_version_minor integer default 0,\n"
" enc_format integer default 0,\n"
" timestamp integer default (datetime('now')),\n"
" primary key (address, user_id)\n"
");\n"
@ -1235,7 +1246,10 @@ DYNAMIC_API PEP_STATUS init(
// Sometimes the user_version wasn't set correctly.
if (version == 1) {
bool version_changed = true;
if (table_contains_column(_session, "revocation_contact_list", "own_address")) {
if (table_contains_column(_session, "identity", "enc_format")) {
version = 14;
}
else if (table_contains_column(_session, "revocation_contact_list", "own_address")) {
version = 13;
}
else if (table_contains_column(_session, "identity", "pEp_version_major")) {
@ -1695,7 +1709,19 @@ DYNAMIC_API PEP_STATUS init(
assert(status == PEP_STATUS_OK);
if (status != PEP_STATUS_OK)
return status;
}
}
if (version < 14) {
int_result = sqlite3_exec(
_session->db,
"alter table identity\n"
" add column enc_format integer default 0;\n",
NULL,
NULL,
NULL
);
assert(int_result == SQLITE_OK);
}
}
else {
// Version from DB was 0, it means this is initial setup.
@ -1909,6 +1935,11 @@ DYNAMIC_API PEP_STATUS init(
NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_set_ident_enc_format,
(int)strlen(sql_set_ident_enc_format), &_session->set_ident_enc_format,
NULL);
assert(int_result == SQLITE_OK);
int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version,
(int)strlen(sql_set_pEp_version), &_session->set_pEp_version,
NULL);
@ -2183,6 +2214,8 @@ DYNAMIC_API void release(PEP_SESSION session)
sqlite3_finalize(session->set_identity_flags);
if (session->unset_identity_flags)
sqlite3_finalize(session->unset_identity_flags);
if (session->set_ident_enc_format)
sqlite3_finalize(session->set_ident_enc_format);
if (session->set_pEp_version)
sqlite3_finalize(session->set_pEp_version);
if (session->exists_trust_entry)
@ -2808,7 +2841,8 @@ DYNAMIC_API PEP_STATUS get_identity(
sqlite3_column_int(session->get_identity, 6);
_identity->minor_ver =
sqlite3_column_int(session->get_identity, 7);
_identity->enc_format =
sqlite3_column_int(session->get_identity, 8);
*identity = _identity;
break;
default:
@ -2886,6 +2920,9 @@ PEP_STATUS get_identities_by_userid(
sqlite3_column_int(session->get_identities_by_userid, 7);
ident->minor_ver =
sqlite3_column_int(session->get_identities_by_userid, 8);
ident->enc_format =
sqlite3_column_int(session->get_identities_by_userid, 9);
identity_list_add(*identities, ident);
ident = NULL;
@ -2956,6 +2993,8 @@ PEP_STATUS get_identities_by_main_key_id(
sqlite3_column_int(session->get_identities_by_main_key_id, 7);
ident->minor_ver =
sqlite3_column_int(session->get_identities_by_main_key_id, 8);
ident->enc_format =
sqlite3_column_int(session->get_identities_by_main_key_id, 9);
identity_list_add(*identities, ident);
ident = NULL;
@ -3030,6 +3069,8 @@ PEP_STATUS get_identity_without_trust_check(
sqlite3_column_int(session->get_identity_without_trust_check, 5);
_identity->minor_ver =
sqlite3_column_int(session->get_identity_without_trust_check, 6);
_identity->enc_format =
sqlite3_column_int(session->get_identity_without_trust_check, 7);
*identity = _identity;
break;
@ -3099,7 +3140,9 @@ PEP_STATUS get_identities_by_address(
sqlite3_column_int(session->get_identities_by_address, 6);
ident->minor_ver =
sqlite3_column_int(session->get_identities_by_address, 7);
ident->enc_format =
sqlite3_column_int(session->get_identities_by_address, 8);
if (ident_list)
identity_list_add(ident_list, ident);
else
@ -3981,6 +4024,38 @@ DYNAMIC_API PEP_STATUS unset_identity_flags(
return PEP_STATUS_OK;
}
DYNAMIC_API PEP_STATUS set_ident_enc_format(
PEP_SESSION session,
pEp_identity *identity,
PEP_enc_format format
)
{
int result;
assert(session);
assert(identity);
assert(identity->address);
assert(identity->user_id);
if (!(session && identity && identity->address && identity->user_id))
return PEP_ILLEGAL_VALUE;
sqlite3_reset(session->set_ident_enc_format);
sqlite3_bind_int(session->set_ident_enc_format, 1, format);
sqlite3_bind_text(session->set_ident_enc_format, 2, identity->address, -1,
SQLITE_STATIC);
sqlite3_bind_text(session->set_ident_enc_format, 3, identity->user_id, -1,
SQLITE_STATIC);
result = sqlite3_step(session->set_ident_enc_format);
sqlite3_reset(session->set_ident_enc_format);
if (result != SQLITE_DONE)
return PEP_CANNOT_SET_IDENTITY;
return PEP_STATUS_OK;
}
PEP_STATUS get_trust_by_userid(PEP_SESSION session, const char* user_id,
labeled_int_list_t** trust_list)
{
@ -4409,7 +4484,7 @@ PEP_STATUS replace_main_user_fpr_if_equal(PEP_SESSION session, const char* user_
const char* new_fpr, const char* compare_fpr) {
assert(session);
assert(user_id);
assert(new_fpr);
assert(compare_fpr);
if (!session || !user_id || !compare_fpr)
return PEP_ILLEGAL_VALUE;

@ -25,12 +25,10 @@ extern "C" {
// RELEASE version this targets
// (string: major.minor.patch)
#define PEP_ENGINE_VERSION "2.1.0"
// Numeric values of above:
#define PEP_ENGINE_VERSION_MAJOR 2
#define PEP_ENGINE_VERSION_MINOR 1
#define PEP_ENGINE_VERSION_PATCH 0
#define PEP_ENGINE_VERSION_RC 9
#define PEP_ENGINE_VERSION_RC 17
#define PEP_OWN_USERID "pEp_own_userId"
@ -156,6 +154,18 @@ typedef enum {
PEP_VERSION_MISMATCH = -7,
} PEP_STATUS;
typedef enum _PEP_enc_format {
PEP_enc_none = 0, // message is not encrypted
PEP_enc_pieces = 1, // inline PGP + PGP extensions, was removed
PEP_enc_inline = 1, // still there
PEP_enc_S_MIME, // RFC5751
PEP_enc_PGP_MIME, // RFC3156
PEP_enc_PEP, // pEp encryption format
PEP_enc_PGP_MIME_Outlook1, // Message B0rken by Outlook type 1
PEP_enc_inline_EA,
PEP_enc_auto = 255 // figure out automatically where possible
} PEP_enc_format;
// messageToSend() - a message needs to be delivered by application
//
@ -627,8 +637,9 @@ typedef struct _pEp_identity {
char lang[3]; // language of conversation
// ISO 639-1 ALPHA-2, last byte is 0
bool me; // if this is the local user herself/himself
unsigned int major_ver; // highest version of pEp message received, if any
unsigned int minor_ver; // highest version of pEp message received, if any
unsigned int major_ver; // highest version of pEp message received, if any
unsigned int minor_ver; // highest version of pEp message received, if any
PEP_enc_format enc_format; // Last specified format we encrypted to for this identity
identity_flags_t flags; // identity_flag1 | identity_flag2 | ...
} pEp_identity;
@ -1453,6 +1464,22 @@ DYNAMIC_API PEP_STATUS config_passphrase(PEP_SESSION session, const char *passph
DYNAMIC_API PEP_STATUS config_passphrase_for_new_keys(PEP_SESSION session,
bool enable,
const char *passphrase);
// set_ident_enc_format() - set the default encryption format for this identity
// (value only MIGHT be used, and only in the case where the
// message enc_format is PEP_enc_auto. It will be used
// opportunistically in the case on a first-come, first-serve
// basis in the order of to_list, cc_list, and bcc_list. We take
// the first set value we come to)
//
// parameters:
// session (in) session handle
// identity (in) identity->user_id and identity->address must NOT be NULL
// format (in) the desired default encryption format
//
DYNAMIC_API PEP_STATUS set_ident_enc_format(PEP_SESSION session,
pEp_identity *identity,
PEP_enc_format format);
PEP_STATUS _generate_keypair(PEP_SESSION session,
pEp_identity *identity,
@ -1524,7 +1551,7 @@ PEP_STATUS exists_person(PEP_SESSION session, pEp_identity* identity, bool* exis
PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, unsigned int new_ver_major, unsigned int new_ver_minor);
PEP_STATUS clear_trust_info(PEP_SESSION session,
const char* user_id,
const char* fpr);
@ -1574,6 +1601,7 @@ PEP_STATUS set_all_userids_to_own(PEP_SESSION session,
PEP_STATUS has_partner_contacted_address(PEP_SESSION session, const char* partner_id,
const char* own_address, bool* was_contacted);
#ifdef __cplusplus
}
#endif

@ -191,6 +191,7 @@ struct _pEpSession {
sqlite3_stmt *exists_identity_entry;
sqlite3_stmt *set_identity_flags;
sqlite3_stmt *unset_identity_flags;
sqlite3_stmt *set_ident_enc_format;
sqlite3_stmt *set_pEp_version;
sqlite3_stmt *clear_trust_info;
sqlite3_stmt *set_trust;

@ -234,6 +234,84 @@ int email_cmp(void *cookie, int a_len, const void *a, int b_len, const void *b)
return result;
}
static PEP_STATUS _pgp_get_decrypted_key(PEP_SESSION session,
pgp_cert_valid_key_iter_t iter,
pgp_key_t* decrypted_key) {
if (!iter)
return PEP_UNKNOWN_ERROR; // ???
if (!decrypted_key)
return PEP_ILLEGAL_VALUE;
PEP_STATUS status = PEP_STATUS_OK;
pgp_error_t err = NULL;
bool bad_pass = false;
bool missing_pass = false;
pgp_key_t key = NULL;
*decrypted_key = NULL;
pgp_valid_key_amalgamation_t ka = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
// FIXME: better error!!!
if (! ka)
ERROR_OUT (err, PEP_UNKNOWN_ERROR,
"%s has no capable key", fpr);
// pgp_key_into_key_pair needs to own the key, but here we
// only get a reference (which we still need to free).
for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {
// pgp_key_into_key_pair needs to own the key, but here we
// only get a reference (which we still need to free).
key = pgp_valid_key_amalgamation_key (ka);
if (pgp_key_has_unencrypted_secret(key))
break;
else {
const char* pass = session->curr_passphrase;
if (pass && pass[0]) {
pgp_key_t decrypted_key = NULL;
decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
strlen(session->curr_passphrase));
pgp_key_free(key);
key = NULL;
if (!decrypted_key) {
bad_pass = true;
continue;
}
else {
key = decrypted_key;
break;
}
}
else {
pgp_key_free(key);
key = NULL;
missing_pass = true;
continue;
}
}
}
if (!key) {
if (bad_pass)
ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
else if (missing_pass)
ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
else
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");
}
out:
pgp_valid_key_amalgamation_free (ka);
*decrypted_key = key;
T("(%s)-> %s", fpr, pEp_status_to_string(status));
return status;
}
PEP_STATUS pgp_init(PEP_SESSION session, bool in_first)
{
PEP_STATUS status = PEP_STATUS_OK;
@ -1854,10 +1932,7 @@ PEP_STATUS pgp_sign_only(
pgp_key_pair_t signing_keypair = NULL;
pgp_signer_t signer = NULL;
pgp_writer_stack_t ws = NULL;
bool bad_pass = false;
bool missing_pass = false;
status = cert_find_by_fpr_hex(session, fpr, true, &signer_cert, NULL);
ERROR_OUT(NULL, status, "Looking up key '%s'", fpr);
@ -1865,60 +1940,14 @@ PEP_STATUS pgp_sign_only(
pgp_cert_valid_key_iter_alive(iter);
pgp_cert_valid_key_iter_revoked(iter, false);
pgp_cert_valid_key_iter_for_signing (iter);
// pgp_cert_valid_key_iter_unencrypted_secret (iter);
// If there are multiple signing capable subkeys, we just take
// the first one, whichever one that happens to be.
ka = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
if (! ka)
ERROR_OUT (err, PEP_UNKNOWN_ERROR,
"%s has no signing capable key", fpr);
// pgp_key_into_key_pair needs to own the key, but here we
// only get a reference (which we still need to free).
pgp_key_t key = NULL;
for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {
// pgp_key_into_key_pair needs to own the key, but here we
// only get a reference (which we still need to free).
key = pgp_valid_key_amalgamation_key (ka);
status = _pgp_get_decrypted_key(session, iter, &key);
if (pgp_key_has_unencrypted_secret(key))
break;
else {
const char* pass = session->curr_passphrase;
if (pass && pass[0]) {
pgp_key_t decrypted_key = NULL;
decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
strlen(session->curr_passphrase));
pgp_key_free(key);
key = NULL;
if (!decrypted_key) {
bad_pass = true;
continue;
}
else {
key = decrypted_key;
break;
}
}
else {
pgp_key_free(key);
key = NULL;
missing_pass = true;
continue;
}
}
}
if (!key) {
if (bad_pass)
ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
else if (missing_pass)
ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
else
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");
}
if (!key || status != PEP_STATUS_OK) {
ERROR_OUT (err, status,
"%s has no signing capable key", fpr);
}
signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
pgp_key_free (key);
@ -2121,68 +2150,20 @@ static PEP_STATUS pgp_encrypt_sign_optional(
// pgp_encrypt_new consumes the recipients (but not the keys).
recipient_count = 0;
bool bad_pass = false;
bool missing_pass = false;
if (sign) {
iter = pgp_cert_valid_key_iter(signer_cert, session->policy, 0);
pgp_cert_valid_key_iter_alive(iter);
pgp_cert_valid_key_iter_revoked(iter, false);
pgp_cert_valid_key_iter_for_signing (iter);
// pgp_cert_valid_key_iter_unencrypted_secret (iter);
// If there are multiple signing capable subkeys, we just take
// the first one, whichever one that happens to be.
ka = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
if (! ka)
ERROR_OUT (err, PEP_UNKNOWN_ERROR,
"%s has no signing capable key", keylist->value);
pgp_key_t key = NULL;
for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {
// pgp_key_into_key_pair needs to own the key, but here we
// only get a reference (which we still need to free).
key = pgp_valid_key_amalgamation_key (ka);
status = _pgp_get_decrypted_key(session, iter, &key);
if (pgp_key_has_unencrypted_secret(key))
break;
else {
const char* pass = session->curr_passphrase;
if (pass && pass[0]) {
pgp_key_t decrypted_key = NULL;
decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
strlen(session->curr_passphrase));
pgp_key_free(key);
key = NULL;
if (!decrypted_key) {
bad_pass = true;
continue;
}
else {
key = decrypted_key;
break;
}
}
else {
pgp_key_free(key);
key = NULL;
missing_pass = true;
continue;
}
}
}
if (!key) {
if (bad_pass)
ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
else if (missing_pass)
ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
else
ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");
}
if (!key || status != PEP_STATUS_OK) {
ERROR_OUT (err, status,
"%s has no signing capable key", fpr);
}
signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
@ -3074,19 +3055,18 @@ PEP_STATUS pgp_renew_key(
iter = pgp_cert_valid_key_iter(cert, session->policy, 0);
pgp_cert_valid_key_iter_for_certification (iter);
pgp_cert_valid_key_iter_unencrypted_secret (iter);
pgp_cert_valid_key_iter_revoked(iter, false);
// If there are multiple certification capable subkeys, we just
// take the first one, whichever one that happens to be.
primary = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
if (! primary)
ERROR_OUT (err, PEP_UNKNOWN_ERROR,
"%s has no usable certification capable key", fpr);
pgp_key_t key = NULL;
status = _pgp_get_decrypted_key(session, iter, &key);
if (!key || status != PEP_STATUS_OK) {
ERROR_OUT (err, status,
"%s has no signing capable key", fpr);