merge default generate_api
authornk
Tue, 07 Jul 2020 11:53:12 +0200
branchgenerate_api
changeset 4827857225aecc3b
parent 4561 6d7492dfeab0
parent 4826 c4cfd953d72c
child 4828 5ab8d79efbe7
merge default
.hgignore
doc/build-macos.md
doc/build-netpgp.md
doc/readme.md
doc/testing.md
src/message.h
src/pgp_gpg.h
test/src/IOS1664Test.cc
     1.1 --- a/.hgtags	Mon Apr 13 13:08:13 2020 +0200
     1.2 +++ b/.hgtags	Tue Jul 07 11:53:12 2020 +0200
     1.3 @@ -27,12 +27,26 @@
     1.4  0000000000000000000000000000000000000000 2.0.0-RC
     1.5  0000000000000000000000000000000000000000 2.0.0-RC
     1.6  c4eb9bb2008fbe531f892fd56f8edce53048eb62 2.0.0-RC
     1.7 -c71ec33fb34612be1d35629de5169f3489975b05 2.0.1_target
     1.8 -c71ec33fb34612be1d35629de5169f3489975b05 2.0.1_target
     1.9 -73516323c7532d71760515d23dd4b36a510f9117 2.0.1_target
    1.10 -0000000000000000000000000000000000000000 2.0.1_target
    1.11 -a0785e8bca3935e0ab7cd82a5826a0fca8d23ccb 2.0.1_target
    1.12 -0000000000000000000000000000000000000000 2.0.1_target
    1.13 -a0785e8bca3935e0ab7cd82a5826a0fca8d23ccb 2.0.1_target
    1.14 -0000000000000000000000000000000000000000 2.0.1_target
    1.15 -f7633443ef921ed222519347720b0a7276b3ef6a 2.0.1_target
    1.16 +c71ec33fb34612be1d35629de5169f3489975b05 Release_2.0.0
    1.17 +b5ce496201c0e534c81d18f8447101e39762ec36 Release_2.0.1
    1.18 +f7633443ef921ed222519347720b0a7276b3ef6a 2.1.0_target
    1.19 +f089504579b7808e60281ba06c9a4eee750939c6 Release_2.0.3
    1.20 +f0e7ec9616c5aa50b42cef70eff8930feb60f7bd decode-encode-API-change
    1.21 +29ddc8a400abbe9b4e05fc5172e5db9ba99f3515 last-old-mime-api-version
    1.22 +c173428cd2c31fcc8867dc1ac785a6637c001210 Restarting default from postrelease
    1.23 +17e8531e1103d93fd8237525c9ecdc7bc4e329e1 Release_2.0.2
    1.24 +e236798013a6453b5162376fdacacd30c1ad15ea Release_2.1.0-RC0
    1.25 +b4d7c37ac8086c6c2b2ff2eb04cd6c203bdcd368 Release_2.1.0-RC1
    1.26 +f5f8da7627e92b4aaf096b09eefaf3763a9a8e63 Release_2.1.0-RC2
    1.27 +3fcdca1ce98953450510ff076e7821593f70133e Release_2.1.0-RC3
    1.28 +ff4532af6b7178f6a24e3d57ffe9c6220d377b21 Release_2.1.0-RC4
    1.29 +d0f73fcb844748ed4523c2b520891a2de4b5d2fb Release_2.1.0-RC5
    1.30 +b54e817b86be2029c8b77115b842e1234979f67e Release_2.1.0-RC6
    1.31 +dc3d3f1c36aa519597e6cdbe579f9c34b0c7dfda Release_2.1.0-RC7
    1.32 +dc3d3f1c36aa519597e6cdbe579f9c34b0c7dfda Release_2.1.0-RC7
    1.33 +99fb132a86ce96b3b87a539fd2344691747ec330 Release_2.1.0-RC7
    1.34 +a046dab8883fbc25a5ca4940e252ce6f0a862002 Release_2.1.0-RC8
    1.35 +f783fb44981d96e46f9454977cec34eb027f9ab2 Release_2.1.0-RC9
    1.36 +3b2ea2c1f5a1c033c1fcc1ee6e7d7ac35778597e Release_2.1.0-RC10
    1.37 +47231c726a380bf53411436a6a21091b6c59f283 Release_2.1.0-RC11
    1.38 +d0150fa70a3df2eeb5b96f68917a910ebcaa4597 Release_2.1.0-RC12
     2.1 --- a/Makefile.conf	Mon Apr 13 13:08:13 2020 +0200
     2.2 +++ b/Makefile.conf	Tue Jul 07 11:53:12 2020 +0200
     2.3 @@ -266,11 +266,22 @@
     2.4  
     2.5  ######### Post processing assignments ########
     2.6  # These variables are ineffective when set anywhere else but here.
     2.7 +# KB: I have no idea why we do this - it totally defeats the purpose of
     2.8 +#     local.conf.
     2.9 +#     For now: set if has no value.
    2.10  ifeq ($(OPENPGP),SEQUOIA)
    2.11 +ifeq ($(SEQUOIA_CFLAGS),)
    2.12      SEQUOIA_CFLAGS=$(shell pkg-config --cflags-only-other sequoia-openpgp)
    2.13 +endif
    2.14 +ifeq ($(SEQUOIA_LDFLAGS),)
    2.15      SEQUOIA_LDFLAGS=$(shell pkg-config --libs-only-l --libs-only-other sequoia-openpgp)
    2.16 +endif
    2.17 +ifeq ($(SEQUOIA_LIB),)
    2.18      SEQUOIA_LIB=$(shell pkg-config --libs-only-L sequoia-openpgp)
    2.19 +endif
    2.20 +ifeq ($(SEQUOIA_INC),)
    2.21      SEQUOIA_INC=$(shell pkg-config --cflags-only-I sequoia-openpgp)
    2.22 +endif
    2.23      CFLAGS+= $(SEQUOIA_CFLAGS)
    2.24      LD_FLAGS+= $(SEQUOIA_LDFLAGS)
    2.25  endif
     3.1 --- a/build-mac/pEpEngine.xcodeproj/project.pbxproj	Mon Apr 13 13:08:13 2020 +0200
     3.2 +++ b/build-mac/pEpEngine.xcodeproj/project.pbxproj	Tue Jul 07 11:53:12 2020 +0200
     3.3 @@ -173,6 +173,8 @@
     3.4  		4378C79223D1AF1700D1AF3F /* ElectGroupKeyResetLeader.c in Sources */ = {isa = PBXBuildFile; fileRef = 4378C79023D1AF1700D1AF3F /* ElectGroupKeyResetLeader.c */; };
     3.5  		438C43B52167752C00C7425B /* labeled_int_list.h in Headers */ = {isa = PBXBuildFile; fileRef = 438C43AF2167752C00C7425B /* labeled_int_list.h */; };
     3.6  		438C43B62167752C00C7425B /* labeled_int_list.c in Sources */ = {isa = PBXBuildFile; fileRef = 438C43B42167752C00C7425B /* labeled_int_list.c */; };
     3.7 +		43C3778E246A8C0300962D22 /* internal_format.h in Headers */ = {isa = PBXBuildFile; fileRef = 43C37788246A8C0300962D22 /* internal_format.h */; };
     3.8 +		43C3778F246A8C0300962D22 /* internal_format.c in Sources */ = {isa = PBXBuildFile; fileRef = 43C3778D246A8C0300962D22 /* internal_format.c */; };
     3.9  		43E4FBB22362C05600BC01F4 /* NegotiationRequestGrouped.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E4FBAD2362C05600BC01F4 /* NegotiationRequestGrouped.c */; };
    3.10  		43E4FBB42362C29100BC01F4 /* GroupHandshake.c in Sources */ = {isa = PBXBuildFile; fileRef = 43E4FBB32362C29100BC01F4 /* GroupHandshake.c */; };
    3.11  		43F6921D1F164A47009418F5 /* resource_id.c in Sources */ = {isa = PBXBuildFile; fileRef = 43F6921C1F164A47009418F5 /* resource_id.c */; };
    3.12 @@ -426,6 +428,8 @@
    3.13  		438C43962167582400C7425B /* sync_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sync_api.h; path = ../src/sync_api.h; sourceTree = "<group>"; };
    3.14  		438C43AF2167752C00C7425B /* labeled_int_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = labeled_int_list.h; path = ../src/labeled_int_list.h; sourceTree = "<group>"; };
    3.15  		438C43B42167752C00C7425B /* labeled_int_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = labeled_int_list.c; path = ../src/labeled_int_list.c; sourceTree = "<group>"; };
    3.16 +		43C37788246A8C0300962D22 /* internal_format.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = internal_format.h; path = ../src/internal_format.h; sourceTree = "<group>"; };
    3.17 +		43C3778D246A8C0300962D22 /* internal_format.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = internal_format.c; path = ../src/internal_format.c; sourceTree = "<group>"; };
    3.18  		43D47A8A225CC60600E97C5B /* pEpTrustWords-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "pEpTrustWords-Info.plist"; path = "/Users/dirk/projects/pEp/pEpEngine/build-mac/pEpTrustWords-Info.plist"; sourceTree = "<absolute>"; };
    3.19  		43E4FBAD2362C05600BC01F4 /* NegotiationRequestGrouped.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = NegotiationRequestGrouped.c; path = ../asn.1/NegotiationRequestGrouped.c; sourceTree = "<group>"; };
    3.20  		43E4FBB32362C29100BC01F4 /* GroupHandshake.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = GroupHandshake.c; path = ../asn.1/GroupHandshake.c; sourceTree = "<group>"; };
    3.21 @@ -728,6 +732,8 @@
    3.22  		64A8264B1B455C5600EECAF0 /* srcref */ = {
    3.23  			isa = PBXGroup;
    3.24  			children = (
    3.25 +				43C3778D246A8C0300962D22 /* internal_format.c */,
    3.26 +				43C37788246A8C0300962D22 /* internal_format.h */,
    3.27  				43188ABE23C4BBDD008EF79C /* distribution_codec.c */,
    3.28  				43188ABF23C4BBDE008EF79C /* distribution_codec.h */,
    3.29  				43188AA223C4B4B3008EF79C /* keyreset_command.c */,
    3.30 @@ -820,6 +826,7 @@
    3.31  				159EF42822B6D3E900149C0C /* pgp_sequoia.h in Headers */,
    3.32  				15B037E222B2B822002D664C /* per_encoder.h in Headers */,
    3.33  				15B0380F22B2B823002D664C /* Sync.h in Headers */,
    3.34 +				43C3778E246A8C0300962D22 /* internal_format.h in Headers */,
    3.35  				15B0380422B2B822002D664C /* constr_SET_OF.h in Headers */,
    3.36  				15B0381322B2B823002D664C /* asn_application.h in Headers */,
    3.37  				15B0380322B2B822002D664C /* OwnKeysRequester.h in Headers */,
    3.38 @@ -1172,6 +1179,7 @@
    3.39  				64A826811B455D0800EECAF0 /* pEpEngine.c in Sources */,
    3.40  				15B037FF22B2B822002D664C /* per_opentype.c in Sources */,
    3.41  				43188A9823C4B2DE008EF79C /* KeySync_fsm.c in Sources */,
    3.42 +				43C3778F246A8C0300962D22 /* internal_format.c in Sources */,
    3.43  			);
    3.44  			runOnlyForDeploymentPostprocessing = 0;
    3.45  		};
     4.1 --- a/build-windows/generate_code.cmd	Mon Apr 13 13:08:13 2020 +0200
     4.2 +++ b/build-windows/generate_code.cmd	Tue Jul 07 11:53:12 2020 +0200
     4.3 @@ -71,6 +71,8 @@
     4.4  DEL *-sample.c
     4.5  
     4.6  CD %pwd%\..
     4.7 -IF NOT EXIST pEp mklink /d pEp pEpEngine\src
     4.8 +RD /S/Q pEp
     4.9 +MKDIR pEp
    4.10 +XCOPY pEpEngine\src\*.h pEp\ /Y/F/I
    4.11  
    4.12  POPD
     5.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj	Mon Apr 13 13:08:13 2020 +0200
     5.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj	Tue Jul 07 11:53:12 2020 +0200
     5.3 @@ -90,13 +90,140 @@
     5.4      <Text Include="ReadMe.txt" />
     5.5    </ItemGroup>
     5.6    <ItemGroup>
     5.7 -    <ClInclude Include="..\..\asn.1\*.h" />
     5.8 +    <None Include="..\generate_code.cmd" />
     5.9    </ItemGroup>
    5.10    <ItemGroup>
    5.11 -    <ClCompile Include="..\..\asn.1\*.c" />
    5.12 +    <ClCompile Include="..\..\asn.1\asn_codecs_prim.c" />
    5.13 +    <ClCompile Include="..\..\asn.1\asn_SEQUENCE_OF.c" />
    5.14 +    <ClCompile Include="..\..\asn.1\asn_SET_OF.c" />
    5.15 +    <ClCompile Include="..\..\asn.1\Beacon.c" />
    5.16 +    <ClCompile Include="..\..\asn.1\ber_decoder.c" />
    5.17 +    <ClCompile Include="..\..\asn.1\ber_tlv_length.c" />
    5.18 +    <ClCompile Include="..\..\asn.1\ber_tlv_tag.c" />
    5.19 +    <ClCompile Include="..\..\asn.1\BIT_STRING.c" />
    5.20 +    <ClCompile Include="..\..\asn.1\BOOLEAN.c" />
    5.21 +    <ClCompile Include="..\..\asn.1\Command.c" />
    5.22 +    <ClCompile Include="..\..\asn.1\Commands.c" />
    5.23 +    <ClCompile Include="..\..\asn.1\CommitAccept.c" />
    5.24 +    <ClCompile Include="..\..\asn.1\CommitAcceptForGroup.c" />
    5.25 +    <ClCompile Include="..\..\asn.1\CommitAcceptOfferer.c" />
    5.26 +    <ClCompile Include="..\..\asn.1\CommitAcceptRequester.c" />
    5.27 +    <ClCompile Include="..\..\asn.1\CommitReject.c" />
    5.28 +    <ClCompile Include="..\..\asn.1\constraints.c" />
    5.29 +    <ClCompile Include="..\..\asn.1\constr_CHOICE.c" />
    5.30 +    <ClCompile Include="..\..\asn.1\constr_SEQUENCE.c" />
    5.31 +    <ClCompile Include="..\..\asn.1\constr_SEQUENCE_OF.c" />
    5.32 +    <ClCompile Include="..\..\asn.1\constr_SET_OF.c" />
    5.33 +    <ClCompile Include="..\..\asn.1\constr_TYPE.c" />
    5.34 +    <ClCompile Include="..\..\asn.1\der_encoder.c" />
    5.35 +    <ClCompile Include="..\..\asn.1\Distribution.c" />
    5.36 +    <ClCompile Include="..\..\asn.1\ElectGroupKeyResetLeader.c" />
    5.37 +    <ClCompile Include="..\..\asn.1\GroupHandshake.c" />
    5.38 +    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c" />
    5.39 +    <ClCompile Include="..\..\asn.1\GroupKeysForNewMember.c" />
    5.40 +    <ClCompile Include="..\..\asn.1\GroupKeysUpdate.c" />
    5.41 +    <ClCompile Include="..\..\asn.1\GroupTrustThisKey.c" />
    5.42 +    <ClCompile Include="..\..\asn.1\Hash.c" />
    5.43 +    <ClCompile Include="..\..\asn.1\Hex.c" />
    5.44 +    <ClCompile Include="..\..\asn.1\Identity.c" />
    5.45 +    <ClCompile Include="..\..\asn.1\IdentityList.c" />
    5.46 +    <ClCompile Include="..\..\asn.1\InitUnledGroupKeyReset.c" />
    5.47 +    <ClCompile Include="..\..\asn.1\INTEGER.c" />
    5.48 +    <ClCompile Include="..\..\asn.1\ISO639-1.c" />
    5.49 +    <ClCompile Include="..\..\asn.1\KeyReset.c" />
    5.50 +    <ClCompile Include="..\..\asn.1\KeySync.c" />
    5.51 +    <ClCompile Include="..\..\asn.1\NativeEnumerated.c" />
    5.52 +    <ClCompile Include="..\..\asn.1\NativeInteger.c" />
    5.53 +    <ClCompile Include="..\..\asn.1\NegotiationOpen.c" />
    5.54 +    <ClCompile Include="..\..\asn.1\NegotiationRequest.c" />
    5.55 +    <ClCompile Include="..\..\asn.1\NegotiationRequestGrouped.c" />
    5.56 +    <ClCompile Include="..\..\asn.1\OCTET_STRING.c" />
    5.57 +    <ClCompile Include="..\..\asn.1\OwnKeysOfferer.c" />
    5.58 +    <ClCompile Include="..\..\asn.1\OwnKeysRequester.c" />
    5.59 +    <ClCompile Include="..\..\asn.1\pdu_collection.c" />
    5.60 +    <ClCompile Include="..\..\asn.1\per_decoder.c" />
    5.61 +    <ClCompile Include="..\..\asn.1\per_encoder.c" />
    5.62 +    <ClCompile Include="..\..\asn.1\per_opentype.c" />
    5.63 +    <ClCompile Include="..\..\asn.1\per_support.c" />
    5.64 +    <ClCompile Include="..\..\asn.1\PrintableString.c" />
    5.65 +    <ClCompile Include="..\..\asn.1\PString.c" />
    5.66 +    <ClCompile Include="..\..\asn.1\Rollback.c" />
    5.67 +    <ClCompile Include="..\..\asn.1\Sync.c" />
    5.68 +    <ClCompile Include="..\..\asn.1\SynchronizeGroupKeys.c" />
    5.69 +    <ClCompile Include="..\..\asn.1\TID.c" />
    5.70 +    <ClCompile Include="..\..\asn.1\UTF8String.c" />
    5.71 +    <ClCompile Include="..\..\asn.1\Version.c" />
    5.72 +    <ClCompile Include="..\..\asn.1\xer_decoder.c" />
    5.73 +    <ClCompile Include="..\..\asn.1\xer_encoder.c" />
    5.74 +    <ClCompile Include="..\..\asn.1\xer_support.c" />
    5.75    </ItemGroup>
    5.76    <ItemGroup>
    5.77 -    <None Include="..\generate_code.cmd" />
    5.78 +    <ClInclude Include="..\..\asn.1\asn_application.h" />
    5.79 +    <ClInclude Include="..\..\asn.1\asn_codecs.h" />
    5.80 +    <ClInclude Include="..\..\asn.1\asn_codecs_prim.h" />
    5.81 +    <ClInclude Include="..\..\asn.1\asn_internal.h" />
    5.82 +    <ClInclude Include="..\..\asn.1\asn_SEQUENCE_OF.h" />
    5.83 +    <ClInclude Include="..\..\asn.1\asn_SET_OF.h" />
    5.84 +    <ClInclude Include="..\..\asn.1\asn_system.h" />
    5.85 +    <ClInclude Include="..\..\asn.1\Beacon.h" />
    5.86 +    <ClInclude Include="..\..\asn.1\ber_decoder.h" />
    5.87 +    <ClInclude Include="..\..\asn.1\ber_tlv_length.h" />
    5.88 +    <ClInclude Include="..\..\asn.1\ber_tlv_tag.h" />
    5.89 +    <ClInclude Include="..\..\asn.1\BIT_STRING.h" />
    5.90 +    <ClInclude Include="..\..\asn.1\BOOLEAN.h" />
    5.91 +    <ClInclude Include="..\..\asn.1\Command.h" />
    5.92 +    <ClInclude Include="..\..\asn.1\Commands.h" />
    5.93 +    <ClInclude Include="..\..\asn.1\CommitAccept.h" />
    5.94 +    <ClInclude Include="..\..\asn.1\CommitAcceptForGroup.h" />
    5.95 +    <ClInclude Include="..\..\asn.1\CommitAcceptOfferer.h" />
    5.96 +    <ClInclude Include="..\..\asn.1\CommitAcceptRequester.h" />
    5.97 +    <ClInclude Include="..\..\asn.1\CommitReject.h" />
    5.98 +    <ClInclude Include="..\..\asn.1\constraints.h" />
    5.99 +    <ClInclude Include="..\..\asn.1\constr_CHOICE.h" />
   5.100 +    <ClInclude Include="..\..\asn.1\constr_SEQUENCE.h" />
   5.101 +    <ClInclude Include="..\..\asn.1\constr_SEQUENCE_OF.h" />
   5.102 +    <ClInclude Include="..\..\asn.1\constr_SET_OF.h" />
   5.103 +    <ClInclude Include="..\..\asn.1\constr_TYPE.h" />
   5.104 +    <ClInclude Include="..\..\asn.1\der_encoder.h" />
   5.105 +    <ClInclude Include="..\..\asn.1\Distribution.h" />
   5.106 +    <ClInclude Include="..\..\asn.1\ElectGroupKeyResetLeader.h" />
   5.107 +    <ClInclude Include="..\..\asn.1\GroupHandshake.h" />
   5.108 +    <ClInclude Include="..\..\asn.1\GroupKeysAndClose.h" />
   5.109 +    <ClInclude Include="..\..\asn.1\GroupKeysForNewMember.h" />
   5.110 +    <ClInclude Include="..\..\asn.1\GroupKeysUpdate.h" />
   5.111 +    <ClInclude Include="..\..\asn.1\GroupTrustThisKey.h" />
   5.112 +    <ClInclude Include="..\..\asn.1\Hash.h" />
   5.113 +    <ClInclude Include="..\..\asn.1\Hex.h" />
   5.114 +    <ClInclude Include="..\..\asn.1\Identity.h" />
   5.115 +    <ClInclude Include="..\..\asn.1\IdentityList.h" />
   5.116 +    <ClInclude Include="..\..\asn.1\InitUnledGroupKeyReset.h" />
   5.117 +    <ClInclude Include="..\..\asn.1\INTEGER.h" />
   5.118 +    <ClInclude Include="..\..\asn.1\ISO639-1.h" />
   5.119 +    <ClInclude Include="..\..\asn.1\KeyReset.h" />
   5.120 +    <ClInclude Include="..\..\asn.1\KeySync.h" />
   5.121 +    <ClInclude Include="..\..\asn.1\NativeEnumerated.h" />
   5.122 +    <ClInclude Include="..\..\asn.1\NativeInteger.h" />
   5.123 +    <ClInclude Include="..\..\asn.1\NegotiationOpen.h" />
   5.124 +    <ClInclude Include="..\..\asn.1\NegotiationRequest.h" />
   5.125 +    <ClInclude Include="..\..\asn.1\NegotiationRequestGrouped.h" />
   5.126 +    <ClInclude Include="..\..\asn.1\OCTET_STRING.h" />
   5.127 +    <ClInclude Include="..\..\asn.1\OwnKeysOfferer.h" />
   5.128 +    <ClInclude Include="..\..\asn.1\OwnKeysRequester.h" />
   5.129 +    <ClInclude Include="..\..\asn.1\per_decoder.h" />
   5.130 +    <ClInclude Include="..\..\asn.1\per_encoder.h" />
   5.131 +    <ClInclude Include="..\..\asn.1\per_opentype.h" />
   5.132 +    <ClInclude Include="..\..\asn.1\per_support.h" />
   5.133 +    <ClInclude Include="..\..\asn.1\PrintableString.h" />
   5.134 +    <ClInclude Include="..\..\asn.1\PString.h" />
   5.135 +    <ClInclude Include="..\..\asn.1\Rollback.h" />
   5.136 +    <ClInclude Include="..\..\asn.1\Sync.h" />
   5.137 +    <ClInclude Include="..\..\asn.1\SynchronizeGroupKeys.h" />
   5.138 +    <ClInclude Include="..\..\asn.1\TID.h" />
   5.139 +    <ClInclude Include="..\..\asn.1\UTF8String.h" />
   5.140 +    <ClInclude Include="..\..\asn.1\Version.h" />
   5.141 +    <ClInclude Include="..\..\asn.1\xer_decoder.h" />
   5.142 +    <ClInclude Include="..\..\asn.1\xer_encoder.h" />
   5.143 +    <ClInclude Include="..\..\asn.1\xer_support.h" />
   5.144    </ItemGroup>
   5.145    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   5.146    <ImportGroup Label="ExtensionTargets" />
     6.1 --- a/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Mon Apr 13 13:08:13 2020 +0200
     6.2 +++ b/build-windows/libpEpasn1/libpEpasn1.vcxproj.filters	Tue Jul 07 11:53:12 2020 +0200
     6.3 @@ -18,1705 +18,397 @@
     6.4      <Text Include="ReadMe.txt" />
     6.5    </ItemGroup>
     6.6    <ItemGroup>
     6.7 -    <ClInclude Include="..\..\asn.1\*.h">
     6.8 -      <Filter>Header Files</Filter>
     6.9 -    </ClInclude>
    6.10 -    <ClInclude Include="..\..\asn.1\*.h">
    6.11 -      <Filter>Header Files</Filter>
    6.12 -    </ClInclude>
    6.13 -    <ClInclude Include="..\..\asn.1\*.h">
    6.14 -      <Filter>Header Files</Filter>
    6.15 -    </ClInclude>
    6.16 -    <ClInclude Include="..\..\asn.1\*.h">
    6.17 -      <Filter>Header Files</Filter>
    6.18 -    </ClInclude>
    6.19 -    <ClInclude Include="..\..\asn.1\*.h">
    6.20 -      <Filter>Header Files</Filter>
    6.21 -    </ClInclude>
    6.22 -    <ClInclude Include="..\..\asn.1\*.h">
    6.23 -      <Filter>Header Files</Filter>
    6.24 -    </ClInclude>
    6.25 -    <ClInclude Include="..\..\asn.1\*.h">
    6.26 -      <Filter>Header Files</Filter>
    6.27 -    </ClInclude>
    6.28 -    <ClInclude Include="..\..\asn.1\*.h">
    6.29 -      <Filter>Header Files</Filter>
    6.30 -    </ClInclude>
    6.31 -    <ClInclude Include="..\..\asn.1\*.h">
    6.32 -      <Filter>Header Files</Filter>
    6.33 -    </ClInclude>
    6.34 -    <ClInclude Include="..\..\asn.1\*.h">
    6.35 -      <Filter>Header Files</Filter>
    6.36 -    </ClInclude>
    6.37 -    <ClInclude Include="..\..\asn.1\*.h">
    6.38 -      <Filter>Header Files</Filter>
    6.39 -    </ClInclude>
    6.40 -    <ClInclude Include="..\..\asn.1\*.h">
    6.41 -      <Filter>Header Files</Filter>
    6.42 -    </ClInclude>
    6.43 -    <ClInclude Include="..\..\asn.1\*.h">
    6.44 -      <Filter>Header Files</Filter>
    6.45 -    </ClInclude>
    6.46 -    <ClInclude Include="..\..\asn.1\*.h">
    6.47 -      <Filter>Header Files</Filter>
    6.48 -    </ClInclude>
    6.49 -    <ClInclude Include="..\..\asn.1\*.h">
    6.50 -      <Filter>Header Files</Filter>
    6.51 -    </ClInclude>
    6.52 -    <ClInclude Include="..\..\asn.1\*.h">
    6.53 -      <Filter>Header Files</Filter>
    6.54 -    </ClInclude>
    6.55 -    <ClInclude Include="..\..\asn.1\*.h">
    6.56 -      <Filter>Header Files</Filter>
    6.57 -    </ClInclude>
    6.58 -    <ClInclude Include="..\..\asn.1\*.h">
    6.59 -      <Filter>Header Files</Filter>
    6.60 -    </ClInclude>
    6.61 -    <ClInclude Include="..\..\asn.1\*.h">
    6.62 -      <Filter>Header Files</Filter>
    6.63 -    </ClInclude>
    6.64 -    <ClInclude Include="..\..\asn.1\*.h">
    6.65 -      <Filter>Header Files</Filter>
    6.66 -    </ClInclude>
    6.67 -    <ClInclude Include="..\..\asn.1\*.h">
    6.68 -      <Filter>Header Files</Filter>
    6.69 -    </ClInclude>
    6.70 -    <ClInclude Include="..\..\asn.1\*.h">
    6.71 -      <Filter>Header Files</Filter>
    6.72 -    </ClInclude>
    6.73 -    <ClInclude Include="..\..\asn.1\*.h">
    6.74 -      <Filter>Header Files</Filter>
    6.75 -    </ClInclude>
    6.76 -    <ClInclude Include="..\..\asn.1\*.h">
    6.77 -      <Filter>Header Files</Filter>
    6.78 -    </ClInclude>
    6.79 -    <ClInclude Include="..\..\asn.1\*.h">
    6.80 -      <Filter>Header Files</Filter>
    6.81 -    </ClInclude>
    6.82 -    <ClInclude Include="..\..\asn.1\*.h">
    6.83 -      <Filter>Header Files</Filter>
    6.84 -    </ClInclude>
    6.85 -    <ClInclude Include="..\..\asn.1\*.h">
    6.86 -      <Filter>Header Files</Filter>
    6.87 -    </ClInclude>
    6.88 -    <ClInclude Include="..\..\asn.1\*.h">
    6.89 -      <Filter>Header Files</Filter>
    6.90 -    </ClInclude>
    6.91 -    <ClInclude Include="..\..\asn.1\*.h">
    6.92 -      <Filter>Header Files</Filter>
    6.93 -    </ClInclude>
    6.94 -    <ClInclude Include="..\..\asn.1\*.h">
    6.95 -      <Filter>Header Files</Filter>
    6.96 -    </ClInclude>
    6.97 -    <ClInclude Include="..\..\asn.1\*.h">
    6.98 -      <Filter>Header Files</Filter>
    6.99 -    </ClInclude>
   6.100 -    <ClInclude Include="..\..\asn.1\*.h">
   6.101 -      <Filter>Header Files</Filter>
   6.102 -    </ClInclude>
   6.103 -    <ClInclude Include="..\..\asn.1\*.h">
   6.104 -      <Filter>Header Files</Filter>
   6.105 -    </ClInclude>
   6.106 -    <ClInclude Include="..\..\asn.1\*.h">
   6.107 -      <Filter>Header Files</Filter>
   6.108 -    </ClInclude>
   6.109 -    <ClInclude Include="..\..\asn.1\*.h">
   6.110 -      <Filter>Header Files</Filter>
   6.111 -    </ClInclude>
   6.112 -    <ClInclude Include="..\..\asn.1\*.h">
   6.113 -      <Filter>Header Files</Filter>
   6.114 -    </ClInclude>
   6.115 -    <ClInclude Include="..\..\asn.1\*.h">
   6.116 -      <Filter>Header Files</Filter>
   6.117 -    </ClInclude>
   6.118 -    <ClInclude Include="..\..\asn.1\*.h">
   6.119 -      <Filter>Header Files</Filter>
   6.120 -    </ClInclude>
   6.121 -    <ClInclude Include="..\..\asn.1\*.h">
   6.122 -      <Filter>Header Files</Filter>
   6.123 -    </ClInclude>
   6.124 -    <ClInclude Include="..\..\asn.1\*.h">
   6.125 -      <Filter>Header Files</Filter>
   6.126 -    </ClInclude>
   6.127 -    <ClInclude Include="..\..\asn.1\*.h">
   6.128 -      <Filter>Header Files</Filter>
   6.129 -    </ClInclude>
   6.130 -    <ClInclude Include="..\..\asn.1\*.h">
   6.131 -      <Filter>Header Files</Filter>
   6.132 -    </ClInclude>
   6.133 -    <ClInclude Include="..\..\asn.1\*.h">
   6.134 -      <Filter>Header Files</Filter>
   6.135 -    </ClInclude>
   6.136 -    <ClInclude Include="..\..\asn.1\*.h">
   6.137 -      <Filter>Header Files</Filter>
   6.138 -    </ClInclude>
   6.139 -    <ClInclude Include="..\..\asn.1\*.h">
   6.140 -      <Filter>Header Files</Filter>
   6.141 -    </ClInclude>
   6.142 -    <ClInclude Include="..\..\asn.1\*.h">
   6.143 -      <Filter>Header Files</Filter>
   6.144 -    </ClInclude>
   6.145 -    <ClInclude Include="..\..\asn.1\*.h">
   6.146 -      <Filter>Header Files</Filter>
   6.147 -    </ClInclude>
   6.148 -    <ClInclude Include="..\..\asn.1\*.h">
   6.149 -      <Filter>Header Files</Filter>
   6.150 -    </ClInclude>
   6.151 -    <ClInclude Include="..\..\asn.1\*.h">
   6.152 -      <Filter>Header Files</Filter>
   6.153 -    </ClInclude>
   6.154 -    <ClInclude Include="..\..\asn.1\*.h">
   6.155 -      <Filter>Header Files</Filter>
   6.156 -    </ClInclude>
   6.157 -    <ClInclude Include="..\..\asn.1\*.h">
   6.158 -      <Filter>Header Files</Filter>
   6.159 -    </ClInclude>
   6.160 -    <ClInclude Include="..\..\asn.1\*.h">
   6.161 -      <Filter>Header Files</Filter>
   6.162 -    </ClInclude>
   6.163 -    <ClInclude Include="..\..\asn.1\*.h">
   6.164 -      <Filter>Header Files</Filter>
   6.165 -    </ClInclude>
   6.166 -    <ClInclude Include="..\..\asn.1\*.h">
   6.167 -      <Filter>Header Files</Filter>
   6.168 -    </ClInclude>
   6.169 -    <ClInclude Include="..\..\asn.1\*.h">
   6.170 -      <Filter>Header Files</Filter>
   6.171 -    </ClInclude>
   6.172 -    <ClInclude Include="..\..\asn.1\*.h">
   6.173 -      <Filter>Header Files</Filter>
   6.174 -    </ClInclude>
   6.175 -    <ClInclude Include="..\..\asn.1\*.h">
   6.176 -      <Filter>Header Files</Filter>
   6.177 -    </ClInclude>
   6.178 -    <ClInclude Include="..\..\asn.1\*.h">
   6.179 -      <Filter>Header Files</Filter>
   6.180 -    </ClInclude>
   6.181 -    <ClInclude Include="..\..\asn.1\*.h">
   6.182 -      <Filter>Header Files</Filter>
   6.183 -    </ClInclude>
   6.184 -    <ClInclude Include="..\..\asn.1\*.h">
   6.185 -      <Filter>Header Files</Filter>
   6.186 -    </ClInclude>
   6.187 -    <ClInclude Include="..\..\asn.1\*.h">
   6.188 -      <Filter>Header Files</Filter>
   6.189 -    </ClInclude>
   6.190 -    <ClInclude Include="..\..\asn.1\*.h">
   6.191 -      <Filter>Header Files</Filter>
   6.192 -    </ClInclude>
   6.193 -    <ClInclude Include="..\..\asn.1\*.h">
   6.194 -      <Filter>Header Files</Filter>
   6.195 -    </ClInclude>
   6.196 -    <ClInclude Include="..\..\asn.1\*.h">
   6.197 -      <Filter>Header Files</Filter>
   6.198 -    </ClInclude>
   6.199 -    <ClInclude Include="..\..\asn.1\*.h">
   6.200 -      <Filter>Header Files</Filter>
   6.201 -    </ClInclude>
   6.202 -    <ClInclude Include="..\..\asn.1\*.h">
   6.203 -      <Filter>Header Files</Filter>
   6.204 -    </ClInclude>
   6.205 -    <ClInclude Include="..\..\asn.1\*.h">
   6.206 -      <Filter>Header Files</Filter>
   6.207 -    </ClInclude>
   6.208 -    <ClInclude Include="..\..\asn.1\*.h">
   6.209 -      <Filter>Header Files</Filter>
   6.210 -    </ClInclude>
   6.211 -    <ClInclude Include="..\..\asn.1\*.h">
   6.212 -      <Filter>Header Files</Filter>
   6.213 -    </ClInclude>
   6.214 -    <ClInclude Include="..\..\asn.1\*.h">
   6.215 -      <Filter>Header Files</Filter>
   6.216 -    </ClInclude>
   6.217 -    <ClInclude Include="..\..\asn.1\*.h">
   6.218 -      <Filter>Header Files</Filter>
   6.219 -    </ClInclude>
   6.220 -    <ClInclude Include="..\..\asn.1\*.h">
   6.221 -      <Filter>Header Files</Filter>
   6.222 -    </ClInclude>
   6.223 -    <ClInclude Include="..\..\asn.1\*.h">
   6.224 -      <Filter>Header Files</Filter>
   6.225 -    </ClInclude>
   6.226 -    <ClInclude Include="..\..\asn.1\*.h">
   6.227 -      <Filter>Header Files</Filter>
   6.228 -    </ClInclude>
   6.229 -    <ClInclude Include="..\..\asn.1\*.h">
   6.230 -      <Filter>Header Files</Filter>
   6.231 -    </ClInclude>
   6.232 -    <ClInclude Include="..\..\asn.1\*.h">
   6.233 -      <Filter>Header Files</Filter>
   6.234 -    </ClInclude>
   6.235 -    <ClInclude Include="..\..\asn.1\*.h">
   6.236 -      <Filter>Header Files</Filter>
   6.237 -    </ClInclude>
   6.238 -    <ClInclude Include="..\..\asn.1\*.h">
   6.239 -      <Filter>Header Files</Filter>
   6.240 -    </ClInclude>
   6.241 -    <ClInclude Include="..\..\asn.1\*.h">
   6.242 -      <Filter>Header Files</Filter>
   6.243 -    </ClInclude>
   6.244 -    <ClInclude Include="..\..\asn.1\*.h">
   6.245 -      <Filter>Header Files</Filter>
   6.246 -    </ClInclude>
   6.247 -    <ClInclude Include="..\..\asn.1\*.h">
   6.248 -      <Filter>Header Files</Filter>
   6.249 -    </ClInclude>
   6.250 -    <ClInclude Include="..\..\asn.1\*.h">
   6.251 -      <Filter>Header Files</Filter>
   6.252 -    </ClInclude>
   6.253 -    <ClInclude Include="..\..\asn.1\*.h">
   6.254 -      <Filter>Header Files</Filter>
   6.255 -    </ClInclude>
   6.256 -    <ClInclude Include="..\..\asn.1\*.h">
   6.257 -      <Filter>Header Files</Filter>
   6.258 -    </ClInclude>
   6.259 -    <ClInclude Include="..\..\asn.1\*.h">
   6.260 -      <Filter>Header Files</Filter>
   6.261 -    </ClInclude>
   6.262 -    <ClInclude Include="..\..\asn.1\*.h">
   6.263 -      <Filter>Header Files</Filter>
   6.264 -    </ClInclude>
   6.265 -    <ClInclude Include="..\..\asn.1\*.h">
   6.266 -      <Filter>Header Files</Filter>
   6.267 -    </ClInclude>
   6.268 -    <ClInclude Include="..\..\asn.1\*.h">
   6.269 -      <Filter>Header Files</Filter>
   6.270 -    </ClInclude>
   6.271 -    <ClInclude Include="..\..\asn.1\*.h">
   6.272 -      <Filter>Header Files</Filter>
   6.273 -    </ClInclude>
   6.274 -    <ClInclude Include="..\..\asn.1\*.h">
   6.275 -      <Filter>Header Files</Filter>
   6.276 -    </ClInclude>
   6.277 -    <ClInclude Include="..\..\asn.1\*.h">
   6.278 -      <Filter>Header Files</Filter>
   6.279 -    </ClInclude>
   6.280 -    <ClInclude Include="..\..\asn.1\*.h">
   6.281 -      <Filter>Header Files</Filter>
   6.282 -    </ClInclude>
   6.283 -    <ClInclude Include="..\..\asn.1\*.h">
   6.284 -      <Filter>Header Files</Filter>
   6.285 -    </ClInclude>
   6.286 -    <ClInclude Include="..\..\asn.1\*.h">
   6.287 -      <Filter>Header Files</Filter>
   6.288 -    </ClInclude>
   6.289 -    <ClInclude Include="..\..\asn.1\*.h">
   6.290 -      <Filter>Header Files</Filter>
   6.291 -    </ClInclude>
   6.292 -    <ClInclude Include="..\..\asn.1\*.h">
   6.293 -      <Filter>Header Files</Filter>
   6.294 -    </ClInclude>
   6.295 -    <ClInclude Include="..\..\asn.1\*.h">
   6.296 -      <Filter>Header Files</Filter>
   6.297 -    </ClInclude>
   6.298 -    <ClInclude Include="..\..\asn.1\*.h">
   6.299 -      <Filter>Header Files</Filter>
   6.300 -    </ClInclude>
   6.301 -    <ClInclude Include="..\..\asn.1\*.h">
   6.302 -      <Filter>Header Files</Filter>
   6.303 -    </ClInclude>
   6.304 -    <ClInclude Include="..\..\asn.1\*.h">
   6.305 -      <Filter>Header Files</Filter>
   6.306 -    </ClInclude>
   6.307 -    <ClInclude Include="..\..\asn.1\*.h">
   6.308 -      <Filter>Header Files</Filter>
   6.309 -    </ClInclude>
   6.310 -    <ClInclude Include="..\..\asn.1\*.h">
   6.311 -      <Filter>Header Files</Filter>
   6.312 -    </ClInclude>
   6.313 -    <ClInclude Include="..\..\asn.1\*.h">
   6.314 -      <Filter>Header Files</Filter>
   6.315 -    </ClInclude>
   6.316 -    <ClInclude Include="..\..\asn.1\*.h">
   6.317 -      <Filter>Header Files</Filter>
   6.318 -    </ClInclude>
   6.319 -    <ClInclude Include="..\..\asn.1\*.h">
   6.320 -      <Filter>Header Files</Filter>
   6.321 -    </ClInclude>
   6.322 -    <ClInclude Include="..\..\asn.1\*.h">
   6.323 -      <Filter>Header Files</Filter>
   6.324 -    </ClInclude>
   6.325 -    <ClInclude Include="..\..\asn.1\*.h">
   6.326 -      <Filter>Header Files</Filter>
   6.327 -    </ClInclude>
   6.328 -    <ClInclude Include="..\..\asn.1\*.h">
   6.329 -      <Filter>Header Files</Filter>
   6.330 -    </ClInclude>
   6.331 -    <ClInclude Include="..\..\asn.1\*.h">
   6.332 -      <Filter>Header Files</Filter>
   6.333 -    </ClInclude>
   6.334 -    <ClInclude Include="..\..\asn.1\*.h">
   6.335 -      <Filter>Header Files</Filter>
   6.336 -    </ClInclude>
   6.337 -    <ClInclude Include="..\..\asn.1\*.h">
   6.338 -      <Filter>Header Files</Filter>
   6.339 -    </ClInclude>
   6.340 -    <ClInclude Include="..\..\asn.1\*.h">
   6.341 -      <Filter>Header Files</Filter>
   6.342 -    </ClInclude>
   6.343 -    <ClInclude Include="..\..\asn.1\*.h">
   6.344 -      <Filter>Header Files</Filter>
   6.345 -    </ClInclude>
   6.346 -    <ClInclude Include="..\..\asn.1\*.h">
   6.347 -      <Filter>Header Files</Filter>
   6.348 -    </ClInclude>
   6.349 -    <ClInclude Include="..\..\asn.1\*.h">
   6.350 -      <Filter>Header Files</Filter>
   6.351 -    </ClInclude>
   6.352 -    <ClInclude Include="..\..\asn.1\*.h">
   6.353 -      <Filter>Header Files</Filter>
   6.354 -    </ClInclude>
   6.355 -    <ClInclude Include="..\..\asn.1\*.h">
   6.356 -      <Filter>Header Files</Filter>
   6.357 -    </ClInclude>
   6.358 -    <ClInclude Include="..\..\asn.1\*.h">
   6.359 -      <Filter>Header Files</Filter>
   6.360 -    </ClInclude>
   6.361 -    <ClInclude Include="..\..\asn.1\*.h">
   6.362 -      <Filter>Header Files</Filter>
   6.363 -    </ClInclude>
   6.364 -    <ClInclude Include="..\..\asn.1\*.h">
   6.365 -      <Filter>Header Files</Filter>
   6.366 -    </ClInclude>
   6.367 -    <ClInclude Include="..\..\asn.1\*.h">
   6.368 -      <Filter>Header Files</Filter>
   6.369 -    </ClInclude>
   6.370 -    <ClInclude Include="..\..\asn.1\*.h">
   6.371 -      <Filter>Header Files</Filter>
   6.372 -    </ClInclude>
   6.373 -    <ClInclude Include="..\..\asn.1\*.h">
   6.374 -      <Filter>Header Files</Filter>
   6.375 -    </ClInclude>
   6.376 -    <ClInclude Include="..\..\asn.1\*.h">
   6.377 -      <Filter>Header Files</Filter>
   6.378 -    </ClInclude>
   6.379 -    <ClInclude Include="..\..\asn.1\*.h">
   6.380 -      <Filter>Header Files</Filter>
   6.381 -    </ClInclude>
   6.382 -    <ClInclude Include="..\..\asn.1\*.h">
   6.383 -      <Filter>Header Files</Filter>
   6.384 -    </ClInclude>
   6.385 -    <ClInclude Include="..\..\asn.1\*.h">
   6.386 -      <Filter>Header Files</Filter>
   6.387 -    </ClInclude>
   6.388 -    <ClInclude Include="..\..\asn.1\*.h">
   6.389 -      <Filter>Header Files</Filter>
   6.390 -    </ClInclude>
   6.391 -    <ClInclude Include="..\..\asn.1\*.h">
   6.392 -      <Filter>Header Files</Filter>
   6.393 -    </ClInclude>
   6.394 -    <ClInclude Include="..\..\asn.1\*.h">
   6.395 -      <Filter>Header Files</Filter>
   6.396 -    </ClInclude>
   6.397 -    <ClInclude Include="..\..\asn.1\*.h">
   6.398 -      <Filter>Header Files</Filter>
   6.399 -    </ClInclude>
   6.400 -    <ClInclude Include="..\..\asn.1\*.h">
   6.401 -      <Filter>Header Files</Filter>
   6.402 -    </ClInclude>
   6.403 -    <ClInclude Include="..\..\asn.1\*.h">
   6.404 -      <Filter>Header Files</Filter>
   6.405 -    </ClInclude>
   6.406 -    <ClInclude Include="..\..\asn.1\*.h">
   6.407 -      <Filter>Header Files</Filter>
   6.408 -    </ClInclude>
   6.409 -    <ClInclude Include="..\..\asn.1\*.h">
   6.410 -      <Filter>Header Files</Filter>
   6.411 -    </ClInclude>
   6.412 -    <ClInclude Include="..\..\asn.1\*.h">
   6.413 -      <Filter>Header Files</Filter>
   6.414 -    </ClInclude>
   6.415 -    <ClInclude Include="..\..\asn.1\*.h">
   6.416 -      <Filter>Header Files</Filter>
   6.417 -    </ClInclude>
   6.418 -    <ClInclude Include="..\..\asn.1\*.h">
   6.419 -      <Filter>Header Files</Filter>
   6.420 -    </ClInclude>
   6.421 -    <ClInclude Include="..\..\asn.1\*.h">
   6.422 -      <Filter>Header Files</Filter>
   6.423 -    </ClInclude>
   6.424 -    <ClInclude Include="..\..\asn.1\*.h">
   6.425 -      <Filter>Header Files</Filter>
   6.426 -    </ClInclude>
   6.427 -    <ClInclude Include="..\..\asn.1\*.h">
   6.428 -      <Filter>Header Files</Filter>
   6.429 -    </ClInclude>
   6.430 -    <ClInclude Include="..\..\asn.1\*.h">
   6.431 -      <Filter>Header Files</Filter>
   6.432 -    </ClInclude>
   6.433 -    <ClInclude Include="..\..\asn.1\*.h">
   6.434 -      <Filter>Header Files</Filter>
   6.435 -    </ClInclude>
   6.436 -    <ClInclude Include="..\..\asn.1\*.h">
   6.437 -      <Filter>Header Files</Filter>
   6.438 -    </ClInclude>
   6.439 -    <ClInclude Include="..\..\asn.1\*.h">
   6.440 -      <Filter>Header Files</Filter>
   6.441 -    </ClInclude>
   6.442 -    <ClInclude Include="..\..\asn.1\*.h">
   6.443 -      <Filter>Header Files</Filter>
   6.444 -    </ClInclude>
   6.445 -    <ClInclude Include="..\..\asn.1\*.h">
   6.446 -      <Filter>Header Files</Filter>
   6.447 -    </ClInclude>
   6.448 -    <ClInclude Include="..\..\asn.1\*.h">
   6.449 -      <Filter>Header Files</Filter>
   6.450 -    </ClInclude>
   6.451 -    <ClInclude Include="..\..\asn.1\*.h">
   6.452 -      <Filter>Header Files</Filter>
   6.453 -    </ClInclude>
   6.454 -    <ClInclude Include="..\..\asn.1\*.h">
   6.455 -      <Filter>Header Files</Filter>
   6.456 -    </ClInclude>
   6.457 -    <ClInclude Include="..\..\asn.1\*.h">
   6.458 -      <Filter>Header Files</Filter>
   6.459 -    </ClInclude>
   6.460 -    <ClInclude Include="..\..\asn.1\*.h">
   6.461 -      <Filter>Header Files</Filter>
   6.462 -    </ClInclude>
   6.463 -    <ClInclude Include="..\..\asn.1\*.h">
   6.464 -      <Filter>Header Files</Filter>
   6.465 -    </ClInclude>
   6.466 -    <ClInclude Include="..\..\asn.1\*.h">
   6.467 -      <Filter>Header Files</Filter>
   6.468 -    </ClInclude>
   6.469 -    <ClInclude Include="..\..\asn.1\*.h">
   6.470 -      <Filter>Header Files</Filter>
   6.471 -    </ClInclude>
   6.472 -    <ClInclude Include="..\..\asn.1\*.h">
   6.473 -      <Filter>Header Files</Filter>
   6.474 -    </ClInclude>
   6.475 -    <ClInclude Include="..\..\asn.1\*.h">
   6.476 -      <Filter>Header Files</Filter>
   6.477 -    </ClInclude>
   6.478 -    <ClInclude Include="..\..\asn.1\*.h">
   6.479 -      <Filter>Header Files</Filter>
   6.480 -    </ClInclude>
   6.481 -    <ClInclude Include="..\..\asn.1\*.h">
   6.482 -      <Filter>Header Files</Filter>
   6.483 -    </ClInclude>
   6.484 -    <ClInclude Include="..\..\asn.1\*.h">
   6.485 -      <Filter>Header Files</Filter>
   6.486 -    </ClInclude>
   6.487 -    <ClInclude Include="..\..\asn.1\*.h">
   6.488 -      <Filter>Header Files</Filter>
   6.489 -    </ClInclude>
   6.490 -    <ClInclude Include="..\..\asn.1\*.h">
   6.491 -      <Filter>Header Files</Filter>
   6.492 -    </ClInclude>
   6.493 -    <ClInclude Include="..\..\asn.1\*.h">
   6.494 -      <Filter>Header Files</Filter>
   6.495 -    </ClInclude>
   6.496 -    <ClInclude Include="..\..\asn.1\*.h">
   6.497 -      <Filter>Header Files</Filter>
   6.498 -    </ClInclude>
   6.499 -    <ClInclude Include="..\..\asn.1\*.h">
   6.500 -      <Filter>Header Files</Filter>
   6.501 -    </ClInclude>
   6.502 -    <ClInclude Include="..\..\asn.1\*.h">
   6.503 -      <Filter>Header Files</Filter>
   6.504 -    </ClInclude>
   6.505 -    <ClInclude Include="..\..\asn.1\*.h">
   6.506 -      <Filter>Header Files</Filter>
   6.507 -    </ClInclude>
   6.508 -    <ClInclude Include="..\..\asn.1\*.h">
   6.509 -      <Filter>Header Files</Filter>
   6.510 -    </ClInclude>
   6.511 -    <ClInclude Include="..\..\asn.1\*.h">
   6.512 -      <Filter>Header Files</Filter>
   6.513 -    </ClInclude>
   6.514 -    <ClInclude Include="..\..\asn.1\*.h">
   6.515 -      <Filter>Header Files</Filter>
   6.516 -    </ClInclude>
   6.517 -    <ClInclude Include="..\..\asn.1\*.h">
   6.518 -      <Filter>Header Files</Filter>
   6.519 -    </ClInclude>
   6.520 -    <ClInclude Include="..\..\asn.1\*.h">
   6.521 -      <Filter>Header Files</Filter>
   6.522 -    </ClInclude>
   6.523 -    <ClInclude Include="..\..\asn.1\*.h">
   6.524 -      <Filter>Header Files</Filter>
   6.525 -    </ClInclude>
   6.526 -    <ClInclude Include="..\..\asn.1\*.h">
   6.527 -      <Filter>Header Files</Filter>
   6.528 -    </ClInclude>
   6.529 -    <ClInclude Include="..\..\asn.1\*.h">
   6.530 -      <Filter>Header Files</Filter>
   6.531 -    </ClInclude>
   6.532 -    <ClInclude Include="..\..\asn.1\*.h">
   6.533 -      <Filter>Header Files</Filter>
   6.534 -    </ClInclude>
   6.535 -    <ClInclude Include="..\..\asn.1\*.h">
   6.536 -      <Filter>Header Files</Filter>
   6.537 -    </ClInclude>
   6.538 -    <ClInclude Include="..\..\asn.1\*.h">
   6.539 -      <Filter>Header Files</Filter>
   6.540 -    </ClInclude>
   6.541 -    <ClInclude Include="..\..\asn.1\*.h">
   6.542 -      <Filter>Header Files</Filter>
   6.543 -    </ClInclude>
   6.544 -    <ClInclude Include="..\..\asn.1\*.h">
   6.545 -      <Filter>Header Files</Filter>
   6.546 -    </ClInclude>
   6.547 -    <ClInclude Include="..\..\asn.1\*.h">
   6.548 -      <Filter>Header Files</Filter>
   6.549 -    </ClInclude>
   6.550 -    <ClInclude Include="..\..\asn.1\*.h">
   6.551 -      <Filter>Header Files</Filter>
   6.552 -    </ClInclude>
   6.553 -    <ClInclude Include="..\..\asn.1\*.h">
   6.554 -      <Filter>Header Files</Filter>
   6.555 -    </ClInclude>
   6.556 -    <ClInclude Include="..\..\asn.1\*.h">
   6.557 -      <Filter>Header Files</Filter>
   6.558 -    </ClInclude>
   6.559 -    <ClInclude Include="..\..\asn.1\*.h">
   6.560 -      <Filter>Header Files</Filter>
   6.561 -    </ClInclude>
   6.562 -    <ClInclude Include="..\..\asn.1\*.h">
   6.563 -      <Filter>Header Files</Filter>
   6.564 -    </ClInclude>
   6.565 -    <ClInclude Include="..\..\asn.1\*.h">
   6.566 -      <Filter>Header Files</Filter>
   6.567 -    </ClInclude>
   6.568 -    <ClInclude Include="..\..\asn.1\*.h">
   6.569 -      <Filter>Header Files</Filter>
   6.570 -    </ClInclude>
   6.571 -    <ClInclude Include="..\..\asn.1\*.h">
   6.572 -      <Filter>Header Files</Filter>
   6.573 -    </ClInclude>
   6.574 -    <ClInclude Include="..\..\asn.1\*.h">
   6.575 -      <Filter>Header Files</Filter>
   6.576 -    </ClInclude>
   6.577 -    <ClInclude Include="..\..\asn.1\*.h">
   6.578 -      <Filter>Header Files</Filter>
   6.579 -    </ClInclude>
   6.580 -    <ClInclude Include="..\..\asn.1\*.h">
   6.581 -      <Filter>Header Files</Filter>
   6.582 -    </ClInclude>
   6.583 -    <ClInclude Include="..\..\asn.1\*.h">
   6.584 -      <Filter>Header Files</Filter>
   6.585 -    </ClInclude>
   6.586 -    <ClInclude Include="..\..\asn.1\*.h">
   6.587 -      <Filter>Header Files</Filter>
   6.588 -    </ClInclude>
   6.589 -    <ClInclude Include="..\..\asn.1\*.h">
   6.590 -      <Filter>Header Files</Filter>
   6.591 -    </ClInclude>
   6.592 -    <ClInclude Include="..\..\asn.1\*.h">
   6.593 -      <Filter>Header Files</Filter>
   6.594 -    </ClInclude>
   6.595 -    <ClInclude Include="..\..\asn.1\*.h">
   6.596 -      <Filter>Header Files</Filter>
   6.597 -    </ClInclude>
   6.598 -    <ClInclude Include="..\..\asn.1\*.h">
   6.599 -      <Filter>Header Files</Filter>
   6.600 -    </ClInclude>
   6.601 -    <ClInclude Include="..\..\asn.1\*.h">
   6.602 -      <Filter>Header Files</Filter>
   6.603 -    </ClInclude>
   6.604 -    <ClInclude Include="..\..\asn.1\*.h">
   6.605 -      <Filter>Header Files</Filter>
   6.606 -    </ClInclude>
   6.607 -    <ClInclude Include="..\..\asn.1\*.h">
   6.608 -      <Filter>Header Files</Filter>
   6.609 -    </ClInclude>
   6.610 -    <ClInclude Include="..\..\asn.1\*.h">
   6.611 -      <Filter>Header Files</Filter>
   6.612 -    </ClInclude>
   6.613 -    <ClInclude Include="..\..\asn.1\*.h">
   6.614 -      <Filter>Header Files</Filter>
   6.615 -    </ClInclude>
   6.616 -    <ClInclude Include="..\..\asn.1\*.h">
   6.617 -      <Filter>Header Files</Filter>
   6.618 -    </ClInclude>
   6.619 -    <ClInclude Include="..\..\asn.1\*.h">
   6.620 -      <Filter>Header Files</Filter>
   6.621 -    </ClInclude>
   6.622 -    <ClInclude Include="..\..\asn.1\*.h">
   6.623 -      <Filter>Header Files</Filter>
   6.624 -    </ClInclude>
   6.625 -    <ClInclude Include="..\..\asn.1\*.h">
   6.626 -      <Filter>Header Files</Filter>
   6.627 -    </ClInclude>
   6.628 -    <ClInclude Include="..\..\asn.1\*.h">
   6.629 -      <Filter>Header Files</Filter>
   6.630 -    </ClInclude>
   6.631 -    <ClInclude Include="..\..\asn.1\*.h">
   6.632 -      <Filter>Header Files</Filter>
   6.633 -    </ClInclude>
   6.634 -    <ClInclude Include="..\..\asn.1\*.h">
   6.635 -      <Filter>Header Files</Filter>
   6.636 -    </ClInclude>
   6.637 -    <ClInclude Include="..\..\asn.1\*.h">
   6.638 -      <Filter>Header Files</Filter>
   6.639 -    </ClInclude>
   6.640 -    <ClInclude Include="..\..\asn.1\*.h">
   6.641 -      <Filter>Header Files</Filter>
   6.642 -    </ClInclude>
   6.643 -    <ClInclude Include="..\..\asn.1\*.h">
   6.644 -      <Filter>Header Files</Filter>
   6.645 -    </ClInclude>
   6.646 -    <ClInclude Include="..\..\asn.1\*.h">
   6.647 -      <Filter>Header Files</Filter>
   6.648 -    </ClInclude>
   6.649 -    <ClInclude Include="..\..\asn.1\*.h">
   6.650 -      <Filter>Header Files</Filter>
   6.651 -    </ClInclude>
   6.652 -    <ClInclude Include="..\..\asn.1\*.h">
   6.653 -      <Filter>Header Files</Filter>
   6.654 -    </ClInclude>
   6.655 -    <ClInclude Include="..\..\asn.1\*.h">
   6.656 -      <Filter>Header Files</Filter>
   6.657 -    </ClInclude>
   6.658 -    <ClInclude Include="..\..\asn.1\*.h">
   6.659 -      <Filter>Header Files</Filter>
   6.660 -    </ClInclude>
   6.661 -    <ClInclude Include="..\..\asn.1\*.h">
   6.662 -      <Filter>Header Files</Filter>
   6.663 -    </ClInclude>
   6.664 -    <ClInclude Include="..\..\asn.1\*.h">
   6.665 -      <Filter>Header Files</Filter>
   6.666 -    </ClInclude>
   6.667 -    <ClInclude Include="..\..\asn.1\*.h">
   6.668 -      <Filter>Header Files</Filter>
   6.669 -    </ClInclude>
   6.670 -    <ClInclude Include="..\..\asn.1\*.h">
   6.671 -      <Filter>Header Files</Filter>
   6.672 -    </ClInclude>
   6.673 -    <ClInclude Include="..\..\asn.1\*.h">
   6.674 -      <Filter>Header Files</Filter>
   6.675 -    </ClInclude>
   6.676 -    <ClInclude Include="..\..\asn.1\*.h">
   6.677 -      <Filter>Header Files</Filter>
   6.678 -    </ClInclude>
   6.679 -    <ClInclude Include="..\..\asn.1\*.h">
   6.680 -      <Filter>Header Files</Filter>
   6.681 -    </ClInclude>
   6.682 -    <ClInclude Include="..\..\asn.1\*.h">
   6.683 -      <Filter>Header Files</Filter>
   6.684 -    </ClInclude>
   6.685 -    <ClInclude Include="..\..\asn.1\*.h">
   6.686 -      <Filter>Header Files</Filter>
   6.687 -    </ClInclude>
   6.688 -    <ClInclude Include="..\..\asn.1\*.h">
   6.689 -      <Filter>Header Files</Filter>
   6.690 -    </ClInclude>
   6.691 -    <ClInclude Include="..\..\asn.1\*.h">
   6.692 -      <Filter>Header Files</Filter>
   6.693 -    </ClInclude>
   6.694 -    <ClInclude Include="..\..\asn.1\*.h">
   6.695 -      <Filter>Header Files</Filter>
   6.696 -    </ClInclude>
   6.697 -    <ClInclude Include="..\..\asn.1\*.h">
   6.698 -      <Filter>Header Files</Filter>
   6.699 -    </ClInclude>
   6.700 -    <ClInclude Include="..\..\asn.1\*.h">
   6.701 -      <Filter>Header Files</Filter>
   6.702 -    </ClInclude>
   6.703 -    <ClInclude Include="..\..\asn.1\*.h">
   6.704 -      <Filter>Header Files</Filter>
   6.705 -    </ClInclude>
   6.706 -    <ClInclude Include="..\..\asn.1\*.h">
   6.707 -      <Filter>Header Files</Filter>
   6.708 -    </ClInclude>
   6.709 -    <ClInclude Include="..\..\asn.1\*.h">
   6.710 -      <Filter>Header Files</Filter>
   6.711 -    </ClInclude>
   6.712 -    <ClInclude Include="..\..\asn.1\*.h">
   6.713 -      <Filter>Header Files</Filter>
   6.714 -    </ClInclude>
   6.715 -    <ClInclude Include="..\..\asn.1\*.h">
   6.716 -      <Filter>Header Files</Filter>
   6.717 -    </ClInclude>
   6.718 -    <ClInclude Include="..\..\asn.1\*.h">
   6.719 -      <Filter>Header Files</Filter>
   6.720 -    </ClInclude>
   6.721 -    <ClInclude Include="..\..\asn.1\*.h">
   6.722 -      <Filter>Header Files</Filter>
   6.723 -    </ClInclude>
   6.724 -    <ClInclude Include="..\..\asn.1\*.h">
   6.725 -      <Filter>Header Files</Filter>
   6.726 -    </ClInclude>
   6.727 -    <ClInclude Include="..\..\asn.1\*.h">
   6.728 -      <Filter>Header Files</Filter>
   6.729 -    </ClInclude>
   6.730 -    <ClInclude Include="..\..\asn.1\*.h">
   6.731 -      <Filter>Header Files</Filter>
   6.732 -    </ClInclude>
   6.733 -    <ClInclude Include="..\..\asn.1\*.h">
   6.734 -      <Filter>Header Files</Filter>
   6.735 -    </ClInclude>
   6.736 -    <ClInclude Include="..\..\asn.1\*.h">
   6.737 -      <Filter>Header Files</Filter>
   6.738 -    </ClInclude>
   6.739 -    <ClInclude Include="..\..\asn.1\*.h">
   6.740 -      <Filter>Header Files</Filter>
   6.741 -    </ClInclude>
   6.742 -    <ClInclude Include="..\..\asn.1\*.h">
   6.743 -      <Filter>Header Files</Filter>
   6.744 -    </ClInclude>
   6.745 -    <ClInclude Include="..\..\asn.1\*.h">
   6.746 -      <Filter>Header Files</Filter>
   6.747 -    </ClInclude>
   6.748 -    <ClInclude Include="..\..\asn.1\*.h">
   6.749 -      <Filter>Header Files</Filter>
   6.750 -    </ClInclude>
   6.751 -    <ClInclude Include="..\..\asn.1\*.h">
   6.752 -      <Filter>Header Files</Filter>
   6.753 -    </ClInclude>
   6.754 -    <ClInclude Include="..\..\asn.1\*.h">
   6.755 -      <Filter>Header Files</Filter>
   6.756 -    </ClInclude>
   6.757 -    <ClInclude Include="..\..\asn.1\*.h">
   6.758 -      <Filter>Header Files</Filter>
   6.759 -    </ClInclude>
   6.760 -    <ClInclude Include="..\..\asn.1\*.h">
   6.761 -      <Filter>Header Files</Filter>
   6.762 -    </ClInclude>
   6.763 -    <ClInclude Include="..\..\asn.1\*.h">
   6.764 -      <Filter>Header Files</Filter>
   6.765 -    </ClInclude>
   6.766 -    <ClInclude Include="..\..\asn.1\*.h">
   6.767 -      <Filter>Header Files</Filter>
   6.768 -    </ClInclude>
   6.769 -    <ClInclude Include="..\..\asn.1\*.h">
   6.770 -      <Filter>Header Files</Filter>
   6.771 -    </ClInclude>
   6.772 -    <ClInclude Include="..\..\asn.1\*.h">
   6.773 -      <Filter>Header Files</Filter>
   6.774 -    </ClInclude>
   6.775 -    <ClInclude Include="..\..\asn.1\*.h">
   6.776 -      <Filter>Header Files</Filter>
   6.777 -    </ClInclude>
   6.778 -    <ClInclude Include="..\..\asn.1\*.h">
   6.779 -      <Filter>Header Files</Filter>
   6.780 -    </ClInclude>
   6.781 -    <ClInclude Include="..\..\asn.1\*.h">
   6.782 -      <Filter>Header Files</Filter>
   6.783 -    </ClInclude>
   6.784 -    <ClInclude Include="..\..\asn.1\*.h">
   6.785 -      <Filter>Header Files</Filter>
   6.786 -    </ClInclude>
   6.787 -    <ClInclude Include="..\..\asn.1\*.h">
   6.788 -      <Filter>Header Files</Filter>
   6.789 -    </ClInclude>
   6.790 -    <ClInclude Include="..\..\asn.1\*.h">
   6.791 -      <Filter>Header Files</Filter>
   6.792 -    </ClInclude>
   6.793 -    <ClInclude Include="..\..\asn.1\*.h">
   6.794 -      <Filter>Header Files</Filter>
   6.795 -    </ClInclude>
   6.796 -    <ClInclude Include="..\..\asn.1\*.h">
   6.797 -      <Filter>Header Files</Filter>
   6.798 -    </ClInclude>
   6.799 -    <ClInclude Include="..\..\asn.1\*.h">
   6.800 -      <Filter>Header Files</Filter>
   6.801 -    </ClInclude>
   6.802 -    <ClInclude Include="..\..\asn.1\*.h">
   6.803 -      <Filter>Header Files</Filter>
   6.804 -    </ClInclude>
   6.805 -    <ClInclude Include="..\..\asn.1\*.h">
   6.806 -      <Filter>Header Files</Filter>
   6.807 -    </ClInclude>
   6.808 -    <ClInclude Include="..\..\asn.1\*.h">
   6.809 -      <Filter>Header Files</Filter>
   6.810 -    </ClInclude>
   6.811 -    <ClInclude Include="..\..\asn.1\*.h">
   6.812 -      <Filter>Header Files</Filter>
   6.813 -    </ClInclude>
   6.814 -    <ClInclude Include="..\..\asn.1\*.h">
   6.815 -      <Filter>Header Files</Filter>
   6.816 -    </ClInclude>
   6.817 -    <ClInclude Include="..\..\asn.1\*.h">
   6.818 -      <Filter>Header Files</Filter>
   6.819 -    </ClInclude>
   6.820 -    <ClInclude Include="..\..\asn.1\*.h">
   6.821 -      <Filter>Header Files</Filter>
   6.822 -    </ClInclude>
   6.823 -    <ClInclude Include="..\..\asn.1\*.h">
   6.824 -      <Filter>Header Files</Filter>
   6.825 -    </ClInclude>
   6.826 -    <ClInclude Include="..\..\asn.1\*.h">
   6.827 -      <Filter>Header Files</Filter>
   6.828 -    </ClInclude>
   6.829 -    <ClInclude Include="..\..\asn.1\*.h">
   6.830 -      <Filter>Header Files</Filter>
   6.831 -    </ClInclude>
   6.832 -    <ClInclude Include="..\..\asn.1\*.h">
   6.833 -      <Filter>Header Files</Filter>
   6.834 -    </ClInclude>
   6.835 -    <ClInclude Include="..\..\asn.1\*.h">
   6.836 -      <Filter>Header Files</Filter>
   6.837 -    </ClInclude>
   6.838 -    <ClInclude Include="..\..\asn.1\*.h">
   6.839 -      <Filter>Header Files</Filter>
   6.840 -    </ClInclude>
   6.841 -    <ClInclude Include="..\..\asn.1\*.h">
   6.842 -      <Filter>Header Files</Filter>
   6.843 -    </ClInclude>
   6.844 -    <ClInclude Include="..\..\asn.1\*.h">
   6.845 -      <Filter>Header Files</Filter>
   6.846 -    </ClInclude>
   6.847 -    <ClInclude Include="..\..\asn.1\*.h">
   6.848 -      <Filter>Header Files</Filter>
   6.849 -    </ClInclude>
   6.850 -    <ClInclude Include="..\..\asn.1\*.h">
   6.851 -      <Filter>Header Files</Filter>
   6.852 -    </ClInclude>
   6.853 -    <ClInclude Include="..\..\asn.1\*.h">
   6.854 -      <Filter>Header Files</Filter>
   6.855 -    </ClInclude>
   6.856 -    <ClInclude Include="..\..\asn.1\*.h">
   6.857 -      <Filter>Header Files</Filter>
   6.858 -    </ClInclude>
   6.859 -    <ClInclude Include="..\..\asn.1\*.h">
   6.860 -      <Filter>Header Files</Filter>
   6.861 -    </ClInclude>
   6.862 -    <ClInclude Include="..\..\asn.1\*.h">
   6.863 -      <Filter>Header Files</Filter>
   6.864 -    </ClInclude>
   6.865 -    <ClInclude Include="..\..\asn.1\*.h">
   6.866 -      <Filter>Header Files</Filter>
   6.867 -    </ClInclude>
   6.868 -    <ClInclude Include="..\..\asn.1\*.h">
   6.869 -      <Filter>Header Files</Filter>
   6.870 -    </ClInclude>
   6.871 -    <ClInclude Include="..\..\asn.1\*.h">
   6.872 -      <Filter>Header Files</Filter>
   6.873 -    </ClInclude>
   6.874 -    <ClInclude Include="..\..\asn.1\*.h">
   6.875 -      <Filter>Header Files</Filter>
   6.876 -    </ClInclude>
   6.877 +    <None Include="..\generate_code.cmd" />
   6.878    </ItemGroup>
   6.879    <ItemGroup>
   6.880 -    <ClCompile Include="..\..\asn.1\*.c">
   6.881 +    <ClCompile Include="..\..\asn.1\asn_codecs_prim.c">
   6.882        <Filter>Source Files</Filter>
   6.883      </ClCompile>
   6.884 -    <ClCompile Include="..\..\asn.1\*.c">
   6.885 +    <ClCompile Include="..\..\asn.1\asn_SEQUENCE_OF.c">
   6.886        <Filter>Source Files</Filter>
   6.887      </ClCompile>
   6.888 -    <ClCompile Include="..\..\asn.1\*.c">
   6.889 +    <ClCompile Include="..\..\asn.1\asn_SET_OF.c">
   6.890        <Filter>Source Files</Filter>
   6.891      </ClCompile>
   6.892 -    <ClCompile Include="..\..\asn.1\*.c">
   6.893 +    <ClCompile Include="..\..\asn.1\Beacon.c">
   6.894        <Filter>Source Files</Filter>
   6.895      </ClCompile>
   6.896 -    <ClCompile Include="..\..\asn.1\*.c">
   6.897 +    <ClCompile Include="..\..\asn.1\ber_decoder.c">
   6.898        <Filter>Source Files</Filter>
   6.899      </ClCompile>
   6.900 -    <ClCompile Include="..\..\asn.1\*.c">
   6.901 +    <ClCompile Include="..\..\asn.1\ber_tlv_length.c">
   6.902        <Filter>Source Files</Filter>
   6.903      </ClCompile>
   6.904 -    <ClCompile Include="..\..\asn.1\*.c">
   6.905 +    <ClCompile Include="..\..\asn.1\ber_tlv_tag.c">
   6.906        <Filter>Source Files</Filter>
   6.907      </ClCompile>
   6.908 -    <ClCompile Include="..\..\asn.1\*.c">
   6.909 +    <ClCompile Include="..\..\asn.1\BIT_STRING.c">
   6.910        <Filter>Source Files</Filter>
   6.911      </ClCompile>
   6.912 -    <ClCompile Include="..\..\asn.1\*.c">
   6.913 +    <ClCompile Include="..\..\asn.1\BOOLEAN.c">
   6.914        <Filter>Source Files</Filter>
   6.915      </ClCompile>
   6.916 -    <ClCompile Include="..\..\asn.1\*.c">
   6.917 +    <ClCompile Include="..\..\asn.1\Command.c">
   6.918        <Filter>Source Files</Filter>
   6.919      </ClCompile>
   6.920 -    <ClCompile Include="..\..\asn.1\*.c">
   6.921 +    <ClCompile Include="..\..\asn.1\Commands.c">
   6.922        <Filter>Source Files</Filter>
   6.923      </ClCompile>
   6.924 -    <ClCompile Include="..\..\asn.1\*.c">
   6.925 +    <ClCompile Include="..\..\asn.1\CommitAccept.c">
   6.926        <Filter>Source Files</Filter>
   6.927      </ClCompile>
   6.928 -    <ClCompile Include="..\..\asn.1\*.c">
   6.929 +    <ClCompile Include="..\..\asn.1\CommitAcceptForGroup.c">
   6.930        <Filter>Source Files</Filter>
   6.931      </ClCompile>
   6.932 -    <ClCompile Include="..\..\asn.1\*.c">
   6.933 +    <ClCompile Include="..\..\asn.1\CommitAcceptOfferer.c">
   6.934        <Filter>Source Files</Filter>
   6.935      </ClCompile>
   6.936 -    <ClCompile Include="..\..\asn.1\*.c">
   6.937 +    <ClCompile Include="..\..\asn.1\CommitAcceptRequester.c">
   6.938        <Filter>Source Files</Filter>
   6.939      </ClCompile>
   6.940 -    <ClCompile Include="..\..\asn.1\*.c">
   6.941 +    <ClCompile Include="..\..\asn.1\CommitReject.c">
   6.942        <Filter>Source Files</Filter>
   6.943      </ClCompile>
   6.944 -    <ClCompile Include="..\..\asn.1\*.c">
   6.945 +    <ClCompile Include="..\..\asn.1\constraints.c">
   6.946        <Filter>Source Files</Filter>
   6.947      </ClCompile>
   6.948 -    <ClCompile Include="..\..\asn.1\*.c">
   6.949 +    <ClCompile Include="..\..\asn.1\constr_CHOICE.c">
   6.950        <Filter>Source Files</Filter>
   6.951      </ClCompile>
   6.952 -    <ClCompile Include="..\..\asn.1\*.c">
   6.953 +    <ClCompile Include="..\..\asn.1\constr_SEQUENCE.c">
   6.954        <Filter>Source Files</Filter>
   6.955      </ClCompile>
   6.956 -    <ClCompile Include="..\..\asn.1\*.c">
   6.957 +    <ClCompile Include="..\..\asn.1\constr_SEQUENCE_OF.c">
   6.958        <Filter>Source Files</Filter>
   6.959      </ClCompile>
   6.960 -    <ClCompile Include="..\..\asn.1\*.c">
   6.961 +    <ClCompile Include="..\..\asn.1\constr_SET_OF.c">
   6.962        <Filter>Source Files</Filter>
   6.963      </ClCompile>
   6.964 -    <ClCompile Include="..\..\asn.1\*.c">
   6.965 +    <ClCompile Include="..\..\asn.1\constr_TYPE.c">
   6.966        <Filter>Source Files</Filter>
   6.967      </ClCompile>
   6.968 -    <ClCompile Include="..\..\asn.1\*.c">
   6.969 +    <ClCompile Include="..\..\asn.1\der_encoder.c">
   6.970        <Filter>Source Files</Filter>
   6.971      </ClCompile>
   6.972 -    <ClCompile Include="..\..\asn.1\*.c">
   6.973 +    <ClCompile Include="..\..\asn.1\Distribution.c">
   6.974        <Filter>Source Files</Filter>
   6.975      </ClCompile>
   6.976 -    <ClCompile Include="..\..\asn.1\*.c">
   6.977 +    <ClCompile Include="..\..\asn.1\ElectGroupKeyResetLeader.c">
   6.978        <Filter>Source Files</Filter>
   6.979      </ClCompile>
   6.980 -    <ClCompile Include="..\..\asn.1\*.c">
   6.981 +    <ClCompile Include="..\..\asn.1\GroupHandshake.c">
   6.982        <Filter>Source Files</Filter>
   6.983      </ClCompile>
   6.984 -    <ClCompile Include="..\..\asn.1\*.c">
   6.985 +    <ClCompile Include="..\..\asn.1\GroupKeysAndClose.c">
   6.986        <Filter>Source Files</Filter>
   6.987      </ClCompile>
   6.988 -    <ClCompile Include="..\..\asn.1\*.c">
   6.989 +    <ClCompile Include="..\..\asn.1\GroupKeysForNewMember.c">
   6.990        <Filter>Source Files</Filter>
   6.991      </ClCompile>
   6.992 -    <ClCompile Include="..\..\asn.1\*.c">
   6.993 +    <ClCompile Include="..\..\asn.1\GroupKeysUpdate.c">
   6.994        <Filter>Source Files</Filter>
   6.995      </ClCompile>
   6.996 -    <ClCompile Include="..\..\asn.1\*.c">
   6.997 +    <ClCompile Include="..\..\asn.1\GroupTrustThisKey.c">
   6.998        <Filter>Source Files</Filter>
   6.999      </ClCompile>
  6.1000 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1001 +    <ClCompile Include="..\..\asn.1\Hash.c">
  6.1002        <Filter>Source Files</Filter>
  6.1003      </ClCompile>
  6.1004 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1005 +    <ClCompile Include="..\..\asn.1\Hex.c">
  6.1006        <Filter>Source Files</Filter>
  6.1007      </ClCompile>
  6.1008 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1009 +    <ClCompile Include="..\..\asn.1\Identity.c">
  6.1010        <Filter>Source Files</Filter>
  6.1011      </ClCompile>
  6.1012 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1013 +    <ClCompile Include="..\..\asn.1\IdentityList.c">
  6.1014        <Filter>Source Files</Filter>
  6.1015      </ClCompile>
  6.1016 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1017 +    <ClCompile Include="..\..\asn.1\InitUnledGroupKeyReset.c">
  6.1018        <Filter>Source Files</Filter>
  6.1019      </ClCompile>
  6.1020 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1021 +    <ClCompile Include="..\..\asn.1\INTEGER.c">
  6.1022        <Filter>Source Files</Filter>
  6.1023      </ClCompile>
  6.1024 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1025 +    <ClCompile Include="..\..\asn.1\ISO639-1.c">
  6.1026        <Filter>Source Files</Filter>
  6.1027      </ClCompile>
  6.1028 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1029 +    <ClCompile Include="..\..\asn.1\KeyReset.c">
  6.1030        <Filter>Source Files</Filter>
  6.1031      </ClCompile>
  6.1032 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1033 +    <ClCompile Include="..\..\asn.1\KeySync.c">
  6.1034        <Filter>Source Files</Filter>
  6.1035      </ClCompile>
  6.1036 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1037 +    <ClCompile Include="..\..\asn.1\NativeEnumerated.c">
  6.1038        <Filter>Source Files</Filter>
  6.1039      </ClCompile>
  6.1040 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1041 +    <ClCompile Include="..\..\asn.1\NativeInteger.c">
  6.1042        <Filter>Source Files</Filter>
  6.1043      </ClCompile>
  6.1044 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1045 +    <ClCompile Include="..\..\asn.1\NegotiationOpen.c">
  6.1046        <Filter>Source Files</Filter>
  6.1047      </ClCompile>
  6.1048 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1049 +    <ClCompile Include="..\..\asn.1\NegotiationRequest.c">
  6.1050        <Filter>Source Files</Filter>
  6.1051      </ClCompile>
  6.1052 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1053 +    <ClCompile Include="..\..\asn.1\NegotiationRequestGrouped.c">
  6.1054        <Filter>Source Files</Filter>
  6.1055      </ClCompile>
  6.1056 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1057 +    <ClCompile Include="..\..\asn.1\OCTET_STRING.c">
  6.1058        <Filter>Source Files</Filter>
  6.1059      </ClCompile>
  6.1060 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1061 +    <ClCompile Include="..\..\asn.1\OwnKeysOfferer.c">
  6.1062        <Filter>Source Files</Filter>
  6.1063      </ClCompile>
  6.1064 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1065 +    <ClCompile Include="..\..\asn.1\OwnKeysRequester.c">
  6.1066        <Filter>Source Files</Filter>
  6.1067      </ClCompile>
  6.1068 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1069 +    <ClCompile Include="..\..\asn.1\pdu_collection.c">
  6.1070        <Filter>Source Files</Filter>
  6.1071      </ClCompile>
  6.1072 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1073 +    <ClCompile Include="..\..\asn.1\per_decoder.c">
  6.1074        <Filter>Source Files</Filter>
  6.1075      </ClCompile>
  6.1076 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1077 +    <ClCompile Include="..\..\asn.1\per_encoder.c">
  6.1078        <Filter>Source Files</Filter>
  6.1079      </ClCompile>
  6.1080 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1081 +    <ClCompile Include="..\..\asn.1\per_opentype.c">
  6.1082        <Filter>Source Files</Filter>
  6.1083      </ClCompile>
  6.1084 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1085 +    <ClCompile Include="..\..\asn.1\per_support.c">
  6.1086        <Filter>Source Files</Filter>
  6.1087      </ClCompile>
  6.1088 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1089 +    <ClCompile Include="..\..\asn.1\PrintableString.c">
  6.1090        <Filter>Source Files</Filter>
  6.1091      </ClCompile>
  6.1092 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1093 +    <ClCompile Include="..\..\asn.1\PString.c">
  6.1094        <Filter>Source Files</Filter>
  6.1095      </ClCompile>
  6.1096 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1097 +    <ClCompile Include="..\..\asn.1\Rollback.c">
  6.1098        <Filter>Source Files</Filter>
  6.1099      </ClCompile>
  6.1100 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1101 +    <ClCompile Include="..\..\asn.1\Sync.c">
  6.1102        <Filter>Source Files</Filter>
  6.1103      </ClCompile>
  6.1104 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1105 +    <ClCompile Include="..\..\asn.1\SynchronizeGroupKeys.c">
  6.1106        <Filter>Source Files</Filter>
  6.1107      </ClCompile>
  6.1108 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1109 +    <ClCompile Include="..\..\asn.1\TID.c">
  6.1110        <Filter>Source Files</Filter>
  6.1111      </ClCompile>
  6.1112 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1113 +    <ClCompile Include="..\..\asn.1\UTF8String.c">
  6.1114        <Filter>Source Files</Filter>
  6.1115      </ClCompile>
  6.1116 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1117 +    <ClCompile Include="..\..\asn.1\Version.c">
  6.1118        <Filter>Source Files</Filter>
  6.1119      </ClCompile>
  6.1120 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1121 +    <ClCompile Include="..\..\asn.1\xer_decoder.c">
  6.1122        <Filter>Source Files</Filter>
  6.1123      </ClCompile>
  6.1124 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1125 +    <ClCompile Include="..\..\asn.1\xer_encoder.c">
  6.1126        <Filter>Source Files</Filter>
  6.1127      </ClCompile>
  6.1128 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1129 -      <Filter>Source Files</Filter>
  6.1130 -    </ClCompile>
  6.1131 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1132 -      <Filter>Source Files</Filter>
  6.1133 -    </ClCompile>
  6.1134 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1135 -      <Filter>Source Files</Filter>
  6.1136 -    </ClCompile>
  6.1137 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1138 -      <Filter>Source Files</Filter>
  6.1139 -    </ClCompile>
  6.1140 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1141 -      <Filter>Source Files</Filter>
  6.1142 -    </ClCompile>
  6.1143 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1144 -      <Filter>Source Files</Filter>
  6.1145 -    </ClCompile>
  6.1146 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1147 -      <Filter>Source Files</Filter>
  6.1148 -    </ClCompile>
  6.1149 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1150 -      <Filter>Source Files</Filter>
  6.1151 -    </ClCompile>
  6.1152 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1153 -      <Filter>Source Files</Filter>
  6.1154 -    </ClCompile>
  6.1155 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1156 -      <Filter>Source Files</Filter>
  6.1157 -    </ClCompile>
  6.1158 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1159 -      <Filter>Source Files</Filter>
  6.1160 -    </ClCompile>
  6.1161 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1162 -      <Filter>Source Files</Filter>
  6.1163 -    </ClCompile>
  6.1164 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1165 -      <Filter>Source Files</Filter>
  6.1166 -    </ClCompile>
  6.1167 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1168 -      <Filter>Source Files</Filter>
  6.1169 -    </ClCompile>
  6.1170 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1171 -      <Filter>Source Files</Filter>
  6.1172 -    </ClCompile>
  6.1173 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1174 -      <Filter>Source Files</Filter>
  6.1175 -    </ClCompile>
  6.1176 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1177 -      <Filter>Source Files</Filter>
  6.1178 -    </ClCompile>
  6.1179 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1180 -      <Filter>Source Files</Filter>
  6.1181 -    </ClCompile>
  6.1182 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1183 -      <Filter>Source Files</Filter>
  6.1184 -    </ClCompile>
  6.1185 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1186 -      <Filter>Source Files</Filter>
  6.1187 -    </ClCompile>
  6.1188 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1189 -      <Filter>Source Files</Filter>
  6.1190 -    </ClCompile>
  6.1191 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1192 -      <Filter>Source Files</Filter>
  6.1193 -    </ClCompile>
  6.1194 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1195 -      <Filter>Source Files</Filter>
  6.1196 -    </ClCompile>
  6.1197 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1198 -      <Filter>Source Files</Filter>
  6.1199 -    </ClCompile>
  6.1200 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1201 -      <Filter>Source Files</Filter>
  6.1202 -    </ClCompile>
  6.1203 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1204 -      <Filter>Source Files</Filter>
  6.1205 -    </ClCompile>
  6.1206 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1207 -      <Filter>Source Files</Filter>
  6.1208 -    </ClCompile>
  6.1209 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1210 -      <Filter>Source Files</Filter>
  6.1211 -    </ClCompile>
  6.1212 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1213 -      <Filter>Source Files</Filter>
  6.1214 -    </ClCompile>
  6.1215 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1216 -      <Filter>Source Files</Filter>
  6.1217 -    </ClCompile>
  6.1218 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1219 -      <Filter>Source Files</Filter>
  6.1220 -    </ClCompile>
  6.1221 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1222 -      <Filter>Source Files</Filter>
  6.1223 -    </ClCompile>
  6.1224 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1225 -      <Filter>Source Files</Filter>
  6.1226 -    </ClCompile>
  6.1227 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1228 -      <Filter>Source Files</Filter>
  6.1229 -    </ClCompile>
  6.1230 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1231 -      <Filter>Source Files</Filter>
  6.1232 -    </ClCompile>
  6.1233 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1234 -      <Filter>Source Files</Filter>
  6.1235 -    </ClCompile>
  6.1236 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1237 -      <Filter>Source Files</Filter>
  6.1238 -    </ClCompile>
  6.1239 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1240 -      <Filter>Source Files</Filter>
  6.1241 -    </ClCompile>
  6.1242 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1243 -      <Filter>Source Files</Filter>
  6.1244 -    </ClCompile>
  6.1245 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1246 -      <Filter>Source Files</Filter>
  6.1247 -    </ClCompile>
  6.1248 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1249 -      <Filter>Source Files</Filter>
  6.1250 -    </ClCompile>
  6.1251 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1252 -      <Filter>Source Files</Filter>
  6.1253 -    </ClCompile>
  6.1254 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1255 -      <Filter>Source Files</Filter>
  6.1256 -    </ClCompile>
  6.1257 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1258 -      <Filter>Source Files</Filter>
  6.1259 -    </ClCompile>
  6.1260 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1261 -      <Filter>Source Files</Filter>
  6.1262 -    </ClCompile>
  6.1263 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1264 -      <Filter>Source Files</Filter>
  6.1265 -    </ClCompile>
  6.1266 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1267 -      <Filter>Source Files</Filter>
  6.1268 -    </ClCompile>
  6.1269 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1270 -      <Filter>Source Files</Filter>
  6.1271 -    </ClCompile>
  6.1272 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1273 -      <Filter>Source Files</Filter>
  6.1274 -    </ClCompile>
  6.1275 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1276 -      <Filter>Source Files</Filter>
  6.1277 -    </ClCompile>
  6.1278 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1279 -      <Filter>Source Files</Filter>
  6.1280 -    </ClCompile>
  6.1281 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1282 -      <Filter>Source Files</Filter>
  6.1283 -    </ClCompile>
  6.1284 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1285 -      <Filter>Source Files</Filter>
  6.1286 -    </ClCompile>
  6.1287 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1288 -      <Filter>Source Files</Filter>
  6.1289 -    </ClCompile>
  6.1290 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1291 -      <Filter>Source Files</Filter>
  6.1292 -    </ClCompile>
  6.1293 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1294 -      <Filter>Source Files</Filter>
  6.1295 -    </ClCompile>
  6.1296 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1297 -      <Filter>Source Files</Filter>
  6.1298 -    </ClCompile>
  6.1299 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1300 -      <Filter>Source Files</Filter>
  6.1301 -    </ClCompile>
  6.1302 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1303 -      <Filter>Source Files</Filter>
  6.1304 -    </ClCompile>
  6.1305 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1306 -      <Filter>Source Files</Filter>
  6.1307 -    </ClCompile>
  6.1308 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1309 -      <Filter>Source Files</Filter>
  6.1310 -    </ClCompile>
  6.1311 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1312 -      <Filter>Source Files</Filter>
  6.1313 -    </ClCompile>
  6.1314 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1315 -      <Filter>Source Files</Filter>
  6.1316 -    </ClCompile>
  6.1317 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1318 -      <Filter>Source Files</Filter>
  6.1319 -    </ClCompile>
  6.1320 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1321 -      <Filter>Source Files</Filter>
  6.1322 -    </ClCompile>
  6.1323 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1324 -      <Filter>Source Files</Filter>
  6.1325 -    </ClCompile>
  6.1326 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1327 -      <Filter>Source Files</Filter>
  6.1328 -    </ClCompile>
  6.1329 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1330 -      <Filter>Source Files</Filter>
  6.1331 -    </ClCompile>
  6.1332 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1333 -      <Filter>Source Files</Filter>
  6.1334 -    </ClCompile>
  6.1335 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1336 -      <Filter>Source Files</Filter>
  6.1337 -    </ClCompile>
  6.1338 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1339 -      <Filter>Source Files</Filter>
  6.1340 -    </ClCompile>
  6.1341 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1342 -      <Filter>Source Files</Filter>
  6.1343 -    </ClCompile>
  6.1344 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1345 -      <Filter>Source Files</Filter>
  6.1346 -    </ClCompile>
  6.1347 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1348 -      <Filter>Source Files</Filter>
  6.1349 -    </ClCompile>
  6.1350 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1351 -      <Filter>Source Files</Filter>
  6.1352 -    </ClCompile>
  6.1353 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1354 -      <Filter>Source Files</Filter>
  6.1355 -    </ClCompile>
  6.1356 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1357 -      <Filter>Source Files</Filter>
  6.1358 -    </ClCompile>
  6.1359 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1360 -      <Filter>Source Files</Filter>
  6.1361 -    </ClCompile>
  6.1362 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1363 -      <Filter>Source Files</Filter>
  6.1364 -    </ClCompile>
  6.1365 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1366 -      <Filter>Source Files</Filter>
  6.1367 -    </ClCompile>
  6.1368 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1369 -      <Filter>Source Files</Filter>
  6.1370 -    </ClCompile>
  6.1371 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1372 -      <Filter>Source Files</Filter>
  6.1373 -    </ClCompile>
  6.1374 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1375 -      <Filter>Source Files</Filter>
  6.1376 -    </ClCompile>
  6.1377 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1378 -      <Filter>Source Files</Filter>
  6.1379 -    </ClCompile>
  6.1380 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1381 -      <Filter>Source Files</Filter>
  6.1382 -    </ClCompile>
  6.1383 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1384 -      <Filter>Source Files</Filter>
  6.1385 -    </ClCompile>
  6.1386 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1387 -      <Filter>Source Files</Filter>
  6.1388 -    </ClCompile>
  6.1389 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1390 -      <Filter>Source Files</Filter>
  6.1391 -    </ClCompile>
  6.1392 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1393 -      <Filter>Source Files</Filter>
  6.1394 -    </ClCompile>
  6.1395 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1396 -      <Filter>Source Files</Filter>
  6.1397 -    </ClCompile>
  6.1398 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1399 -      <Filter>Source Files</Filter>
  6.1400 -    </ClCompile>
  6.1401 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1402 -      <Filter>Source Files</Filter>
  6.1403 -    </ClCompile>
  6.1404 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1405 -      <Filter>Source Files</Filter>
  6.1406 -    </ClCompile>
  6.1407 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1408 -      <Filter>Source Files</Filter>
  6.1409 -    </ClCompile>
  6.1410 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1411 -      <Filter>Source Files</Filter>
  6.1412 -    </ClCompile>
  6.1413 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1414 -      <Filter>Source Files</Filter>
  6.1415 -    </ClCompile>
  6.1416 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1417 -      <Filter>Source Files</Filter>
  6.1418 -    </ClCompile>
  6.1419 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1420 -      <Filter>Source Files</Filter>
  6.1421 -    </ClCompile>
  6.1422 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1423 -      <Filter>Source Files</Filter>
  6.1424 -    </ClCompile>
  6.1425 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1426 -      <Filter>Source Files</Filter>
  6.1427 -    </ClCompile>
  6.1428 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1429 -      <Filter>Source Files</Filter>
  6.1430 -    </ClCompile>
  6.1431 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1432 -      <Filter>Source Files</Filter>
  6.1433 -    </ClCompile>
  6.1434 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1435 -      <Filter>Source Files</Filter>
  6.1436 -    </ClCompile>
  6.1437 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1438 -      <Filter>Source Files</Filter>
  6.1439 -    </ClCompile>
  6.1440 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1441 -      <Filter>Source Files</Filter>
  6.1442 -    </ClCompile>
  6.1443 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1444 -      <Filter>Source Files</Filter>
  6.1445 -    </ClCompile>
  6.1446 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1447 -      <Filter>Source Files</Filter>
  6.1448 -    </ClCompile>
  6.1449 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1450 -      <Filter>Source Files</Filter>
  6.1451 -    </ClCompile>
  6.1452 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1453 -      <Filter>Source Files</Filter>
  6.1454 -    </ClCompile>
  6.1455 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1456 -      <Filter>Source Files</Filter>
  6.1457 -    </ClCompile>
  6.1458 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1459 -      <Filter>Source Files</Filter>
  6.1460 -    </ClCompile>
  6.1461 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1462 -      <Filter>Source Files</Filter>
  6.1463 -    </ClCompile>
  6.1464 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1465 -      <Filter>Source Files</Filter>
  6.1466 -    </ClCompile>
  6.1467 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1468 -      <Filter>Source Files</Filter>
  6.1469 -    </ClCompile>
  6.1470 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1471 -      <Filter>Source Files</Filter>
  6.1472 -    </ClCompile>
  6.1473 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1474 -      <Filter>Source Files</Filter>
  6.1475 -    </ClCompile>
  6.1476 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1477 -      <Filter>Source Files</Filter>
  6.1478 -    </ClCompile>
  6.1479 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1480 -      <Filter>Source Files</Filter>
  6.1481 -    </ClCompile>
  6.1482 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1483 -      <Filter>Source Files</Filter>
  6.1484 -    </ClCompile>
  6.1485 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1486 -      <Filter>Source Files</Filter>
  6.1487 -    </ClCompile>
  6.1488 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1489 -      <Filter>Source Files</Filter>
  6.1490 -    </ClCompile>
  6.1491 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1492 -      <Filter>Source Files</Filter>
  6.1493 -    </ClCompile>
  6.1494 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1495 -      <Filter>Source Files</Filter>
  6.1496 -    </ClCompile>
  6.1497 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1498 -      <Filter>Source Files</Filter>
  6.1499 -    </ClCompile>
  6.1500 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1501 -      <Filter>Source Files</Filter>
  6.1502 -    </ClCompile>
  6.1503 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1504 -      <Filter>Source Files</Filter>
  6.1505 -    </ClCompile>
  6.1506 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1507 -      <Filter>Source Files</Filter>
  6.1508 -    </ClCompile>
  6.1509 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1510 -      <Filter>Source Files</Filter>
  6.1511 -    </ClCompile>
  6.1512 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1513 -      <Filter>Source Files</Filter>
  6.1514 -    </ClCompile>
  6.1515 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1516 -      <Filter>Source Files</Filter>
  6.1517 -    </ClCompile>
  6.1518 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1519 -      <Filter>Source Files</Filter>
  6.1520 -    </ClCompile>
  6.1521 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1522 -      <Filter>Source Files</Filter>
  6.1523 -    </ClCompile>
  6.1524 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1525 -      <Filter>Source Files</Filter>
  6.1526 -    </ClCompile>
  6.1527 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1528 -      <Filter>Source Files</Filter>
  6.1529 -    </ClCompile>
  6.1530 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1531 -      <Filter>Source Files</Filter>
  6.1532 -    </ClCompile>
  6.1533 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1534 -      <Filter>Source Files</Filter>
  6.1535 -    </ClCompile>
  6.1536 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1537 -      <Filter>Source Files</Filter>
  6.1538 -    </ClCompile>
  6.1539 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1540 -      <Filter>Source Files</Filter>
  6.1541 -    </ClCompile>
  6.1542 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1543 -      <Filter>Source Files</Filter>
  6.1544 -    </ClCompile>
  6.1545 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1546 -      <Filter>Source Files</Filter>
  6.1547 -    </ClCompile>
  6.1548 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1549 -      <Filter>Source Files</Filter>
  6.1550 -    </ClCompile>
  6.1551 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1552 -      <Filter>Source Files</Filter>
  6.1553 -    </ClCompile>
  6.1554 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1555 -      <Filter>Source Files</Filter>
  6.1556 -    </ClCompile>
  6.1557 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1558 -      <Filter>Source Files</Filter>
  6.1559 -    </ClCompile>
  6.1560 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1561 -      <Filter>Source Files</Filter>
  6.1562 -    </ClCompile>
  6.1563 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1564 -      <Filter>Source Files</Filter>
  6.1565 -    </ClCompile>
  6.1566 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1567 -      <Filter>Source Files</Filter>
  6.1568 -    </ClCompile>
  6.1569 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1570 -      <Filter>Source Files</Filter>
  6.1571 -    </ClCompile>
  6.1572 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1573 -      <Filter>Source Files</Filter>
  6.1574 -    </ClCompile>
  6.1575 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1576 -      <Filter>Source Files</Filter>
  6.1577 -    </ClCompile>
  6.1578 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1579 -      <Filter>Source Files</Filter>
  6.1580 -    </ClCompile>
  6.1581 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1582 -      <Filter>Source Files</Filter>
  6.1583 -    </ClCompile>
  6.1584 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1585 -      <Filter>Source Files</Filter>
  6.1586 -    </ClCompile>
  6.1587 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1588 -      <Filter>Source Files</Filter>
  6.1589 -    </ClCompile>
  6.1590 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1591 -      <Filter>Source Files</Filter>
  6.1592 -    </ClCompile>
  6.1593 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1594 -      <Filter>Source Files</Filter>
  6.1595 -    </ClCompile>
  6.1596 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1597 -      <Filter>Source Files</Filter>
  6.1598 -    </ClCompile>
  6.1599 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1600 -      <Filter>Source Files</Filter>
  6.1601 -    </ClCompile>
  6.1602 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1603 -      <Filter>Source Files</Filter>
  6.1604 -    </ClCompile>
  6.1605 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1606 -      <Filter>Source Files</Filter>
  6.1607 -    </ClCompile>
  6.1608 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1609 -      <Filter>Source Files</Filter>
  6.1610 -    </ClCompile>
  6.1611 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1612 -      <Filter>Source Files</Filter>
  6.1613 -    </ClCompile>
  6.1614 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1615 -      <Filter>Source Files</Filter>
  6.1616 -    </ClCompile>
  6.1617 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1618 -      <Filter>Source Files</Filter>
  6.1619 -    </ClCompile>
  6.1620 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1621 -      <Filter>Source Files</Filter>
  6.1622 -    </ClCompile>
  6.1623 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1624 -      <Filter>Source Files</Filter>
  6.1625 -    </ClCompile>
  6.1626 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1627 -      <Filter>Source Files</Filter>
  6.1628 -    </ClCompile>
  6.1629 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1630 -      <Filter>Source Files</Filter>
  6.1631 -    </ClCompile>
  6.1632 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1633 -      <Filter>Source Files</Filter>
  6.1634 -    </ClCompile>
  6.1635 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1636 -      <Filter>Source Files</Filter>
  6.1637 -    </ClCompile>
  6.1638 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1639 -      <Filter>Source Files</Filter>
  6.1640 -    </ClCompile>
  6.1641 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1642 -      <Filter>Source Files</Filter>
  6.1643 -    </ClCompile>
  6.1644 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1645 -      <Filter>Source Files</Filter>
  6.1646 -    </ClCompile>
  6.1647 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1648 -      <Filter>Source Files</Filter>
  6.1649 -    </ClCompile>
  6.1650 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1651 -      <Filter>Source Files</Filter>
  6.1652 -    </ClCompile>
  6.1653 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1654 -      <Filter>Source Files</Filter>
  6.1655 -    </ClCompile>
  6.1656 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1657 -      <Filter>Source Files</Filter>
  6.1658 -    </ClCompile>
  6.1659 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1660 -      <Filter>Source Files</Filter>
  6.1661 -    </ClCompile>
  6.1662 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1663 -      <Filter>Source Files</Filter>
  6.1664 -    </ClCompile>
  6.1665 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1666 -      <Filter>Source Files</Filter>
  6.1667 -    </ClCompile>
  6.1668 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1669 -      <Filter>Source Files</Filter>
  6.1670 -    </ClCompile>
  6.1671 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1672 -      <Filter>Source Files</Filter>
  6.1673 -    </ClCompile>
  6.1674 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1675 -      <Filter>Source Files</Filter>
  6.1676 -    </ClCompile>
  6.1677 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1678 -      <Filter>Source Files</Filter>
  6.1679 -    </ClCompile>
  6.1680 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1681 -      <Filter>Source Files</Filter>
  6.1682 -    </ClCompile>
  6.1683 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1684 -      <Filter>Source Files</Filter>
  6.1685 -    </ClCompile>
  6.1686 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1687 -      <Filter>Source Files</Filter>
  6.1688 -    </ClCompile>
  6.1689 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1690 -      <Filter>Source Files</Filter>
  6.1691 -    </ClCompile>
  6.1692 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1693 -      <Filter>Source Files</Filter>
  6.1694 -    </ClCompile>
  6.1695 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1696 -      <Filter>Source Files</Filter>
  6.1697 -    </ClCompile>
  6.1698 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1699 -      <Filter>Source Files</Filter>
  6.1700 -    </ClCompile>
  6.1701 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1702 -      <Filter>Source Files</Filter>
  6.1703 -    </ClCompile>
  6.1704 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1705 -      <Filter>Source Files</Filter>
  6.1706 -    </ClCompile>
  6.1707 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1708 -      <Filter>Source Files</Filter>
  6.1709 -    </ClCompile>
  6.1710 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1711 -      <Filter>Source Files</Filter>
  6.1712 -    </ClCompile>
  6.1713 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1714 -      <Filter>Source Files</Filter>
  6.1715 -    </ClCompile>
  6.1716 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1717 -      <Filter>Source Files</Filter>
  6.1718 -    </ClCompile>
  6.1719 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1720 -      <Filter>Source Files</Filter>
  6.1721 -    </ClCompile>
  6.1722 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1723 -      <Filter>Source Files</Filter>
  6.1724 -    </ClCompile>
  6.1725 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1726 -      <Filter>Source Files</Filter>
  6.1727 -    </ClCompile>
  6.1728 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1729 -      <Filter>Source Files</Filter>
  6.1730 -    </ClCompile>
  6.1731 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1732 -      <Filter>Source Files</Filter>
  6.1733 -    </ClCompile>
  6.1734 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1735 -      <Filter>Source Files</Filter>
  6.1736 -    </ClCompile>
  6.1737 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1738 -      <Filter>Source Files</Filter>
  6.1739 -    </ClCompile>
  6.1740 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1741 -      <Filter>Source Files</Filter>
  6.1742 -    </ClCompile>
  6.1743 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1744 -      <Filter>Source Files</Filter>
  6.1745 -    </ClCompile>
  6.1746 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1747 -      <Filter>Source Files</Filter>
  6.1748 -    </ClCompile>
  6.1749 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1750 -      <Filter>Source Files</Filter>
  6.1751 -    </ClCompile>
  6.1752 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1753 -      <Filter>Source Files</Filter>
  6.1754 -    </ClCompile>
  6.1755 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1756 -      <Filter>Source Files</Filter>
  6.1757 -    </ClCompile>
  6.1758 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1759 -      <Filter>Source Files</Filter>
  6.1760 -    </ClCompile>
  6.1761 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1762 -      <Filter>Source Files</Filter>
  6.1763 -    </ClCompile>
  6.1764 -    <ClCompile Include="..\..\asn.1\*.c">
  6.1765 +    <ClCompile Include="..\..\asn.1\xer_support.c">
  6.1766        <Filter>Source Files</Filter>
  6.1767      </ClCompile>
  6.1768    </ItemGroup>
  6.1769    <ItemGroup>
  6.1770 -    <None Include="..\generate_code.cmd" />
  6.1771 +    <ClInclude Include="..\..\asn.1\asn_application.h">
  6.1772 +      <Filter>Header Files</Filter>
  6.1773 +    </ClInclude>
  6.1774 +    <ClInclude Include="..\..\asn.1\asn_codecs.h">
  6.1775 +      <Filter>Header Files</Filter>
  6.1776 +    </ClInclude>
  6.1777 +    <ClInclude Include="..\..\asn.1\asn_codecs_prim.h">
  6.1778 +      <Filter>Header Files</Filter>
  6.1779 +    </ClInclude>
  6.1780 +    <ClInclude Include="..\..\asn.1\asn_internal.h">
  6.1781 +      <Filter>Header Files</Filter>
  6.1782 +    </ClInclude>
  6.1783 +    <ClInclude Include="..\..\asn.1\asn_SEQUENCE_OF.h">
  6.1784 +      <Filter>Header Files</Filter>
  6.1785 +    </ClInclude>
  6.1786 +    <ClInclude Include="..\..\asn.1\asn_SET_OF.h">
  6.1787 +      <Filter>Header Files</Filter>
  6.1788 +    </ClInclude>
  6.1789 +    <ClInclude Include="..\..\asn.1\asn_system.h">
  6.1790 +      <Filter>Header Files</Filter>
  6.1791 +    </ClInclude>
  6.1792 +    <ClInclude Include="..\..\asn.1\Beacon.h">
  6.1793 +      <Filter>Header Files</Filter>
  6.1794 +    </ClInclude>
  6.1795 +    <ClInclude Include="..\..\asn.1\ber_decoder.h">
  6.1796 +      <Filter>Header Files</Filter>
  6.1797 +    </ClInclude>
  6.1798 +    <ClInclude Include="..\..\asn.1\ber_tlv_length.h">
  6.1799 +      <Filter>Header Files</Filter>
  6.1800 +    </ClInclude>
  6.1801 +    <ClInclude Include="..\..\asn.1\ber_tlv_tag.h">
  6.1802 +      <Filter>Header Files</Filter>
  6.1803 +    </ClInclude>
  6.1804 +    <ClInclude Include="..\..\asn.1\BIT_STRING.h">
  6.1805 +      <Filter>Header Files</Filter>
  6.1806 +    </ClInclude>
  6.1807 +    <ClInclude Include="..\..\asn.1\BOOLEAN.h">
  6.1808 +      <Filter>Header Files</Filter>
  6.1809 +    </ClInclude>
  6.1810 +    <ClInclude Include="..\..\asn.1\Command.h">
  6.1811 +      <Filter>Header Files</Filter>
  6.1812 +    </ClInclude>
  6.1813 +    <ClInclude Include="..\..\asn.1\Commands.h">
  6.1814 +      <Filter>Header Files</Filter>
  6.1815 +    </ClInclude>
  6.1816 +    <ClInclude Include="..\..\asn.1\CommitAccept.h">
  6.1817 +      <Filter>Header Files</Filter>
  6.1818 +    </ClInclude>
  6.1819 +    <ClInclude Include="..\..\asn.1\CommitAcceptForGroup.h">
  6.1820 +      <Filter>Header Files</Filter>
  6.1821 +    </ClInclude>
  6.1822 +    <ClInclude Include="..\..\asn.1\CommitAcceptOfferer.h">
  6.1823 +      <Filter>Header Files</Filter>
  6.1824 +    </ClInclude>
  6.1825 +    <ClInclude Include="..\..\asn.1\CommitAcceptRequester.h">
  6.1826 +      <Filter>Header Files</Filter>
  6.1827 +    </ClInclude>
  6.1828 +    <ClInclude Include="..\..\asn.1\CommitReject.h">
  6.1829 +      <Filter>Header Files</Filter>
  6.1830 +    </ClInclude>
  6.1831 +    <ClInclude Include="..\..\asn.1\constraints.h">
  6.1832 +      <Filter>Header Files</Filter>
  6.1833 +    </ClInclude>
  6.1834 +    <ClInclude Include="..\..\asn.1\constr_CHOICE.h">
  6.1835 +      <Filter>Header Files</Filter>
  6.1836 +    </ClInclude>
  6.1837 +    <ClInclude Include="..\..\asn.1\constr_SEQUENCE.h">
  6.1838 +      <Filter>Header Files</Filter>
  6.1839 +    </ClInclude>
  6.1840 +    <ClInclude Include="..\..\asn.1\constr_SEQUENCE_OF.h">
  6.1841 +      <Filter>Header Files</Filter>
  6.1842 +    </ClInclude>
  6.1843 +    <ClInclude Include="..\..\asn.1\constr_SET_OF.h">
  6.1844 +      <Filter>Header Files</Filter>
  6.1845 +    </ClInclude>
  6.1846 +    <ClInclude Include="..\..\asn.1\constr_TYPE.h">
  6.1847 +      <Filter>Header Files</Filter>
  6.1848 +    </ClInclude>
  6.1849 +    <ClInclude Include="..\..\asn.1\der_encoder.h">
  6.1850 +      <Filter>Header Files</Filter>
  6.1851 +    </ClInclude>
  6.1852 +    <ClInclude Include="..\..\asn.1\Distribution.h">
  6.1853 +      <Filter>Header Files</Filter>
  6.1854 +    </ClInclude>
  6.1855 +    <ClInclude Include="..\..\asn.1\ElectGroupKeyResetLeader.h">
  6.1856 +      <Filter>Header Files</Filter>
  6.1857 +    </ClInclude>
  6.1858 +    <ClInclude Include="..\..\asn.1\GroupHandshake.h">
  6.1859 +      <Filter>Header Files</Filter>
  6.1860 +    </ClInclude>
  6.1861 +    <ClInclude Include="..\..\asn.1\GroupKeysAndClose.h">
  6.1862 +      <Filter>Header Files</Filter>
  6.1863 +    </ClInclude>
  6.1864 +    <ClInclude Include="..\..\asn.1\GroupKeysForNewMember.h">
  6.1865 +      <Filter>Header Files</Filter>
  6.1866 +    </ClInclude>
  6.1867 +    <ClInclude Include="..\..\asn.1\GroupKeysUpdate.h">
  6.1868 +      <Filter>Header Files</Filter>
  6.1869 +    </ClInclude>
  6.1870 +    <ClInclude Include="..\..\asn.1\GroupTrustThisKey.h">
  6.1871 +      <Filter>Header Files</Filter>
  6.1872 +    </ClInclude>
  6.1873 +    <ClInclude Include="..\..\asn.1\Hash.h">
  6.1874 +      <Filter>Header Files</Filter>
  6.1875 +    </ClInclude>
  6.1876 +    <ClInclude Include="..\..\asn.1\Hex.h">
  6.1877 +      <Filter>Header Files</Filter>
  6.1878 +    </ClInclude>
  6.1879 +    <ClInclude Include="..\..\asn.1\Identity.h">
  6.1880 +      <Filter>Header Files</Filter>
  6.1881 +    </ClInclude>
  6.1882 +    <ClInclude Include="..\..\asn.1\IdentityList.h">
  6.1883 +      <Filter>Header Files</Filter>
  6.1884 +    </ClInclude>
  6.1885 +    <ClInclude Include="..\..\asn.1\InitUnledGroupKeyReset.h">
  6.1886 +      <Filter>Header Files</Filter>
  6.1887 +    </ClInclude>
  6.1888 +    <ClInclude Include="..\..\asn.1\INTEGER.h">
  6.1889 +      <Filter>Header Files</Filter>
  6.1890 +    </ClInclude>
  6.1891 +    <ClInclude Include="..\..\asn.1\ISO639-1.h">
  6.1892 +      <Filter>Header Files</Filter>
  6.1893 +    </ClInclude>
  6.1894 +    <ClInclude Include="..\..\asn.1\KeyReset.h">
  6.1895 +      <Filter>Header Files</Filter>
  6.1896 +    </ClInclude>
  6.1897 +    <ClInclude Include="..\..\asn.1\KeySync.h">
  6.1898 +      <Filter>Header Files</Filter>
  6.1899 +    </ClInclude>
  6.1900 +    <ClInclude Include="..\..\asn.1\NativeEnumerated.h">
  6.1901 +      <Filter>Header Files</Filter>
  6.1902 +    </ClInclude>
  6.1903 +    <ClInclude Include="..\..\asn.1\NativeInteger.h">
  6.1904 +      <Filter>Header Files</Filter>
  6.1905 +    </ClInclude>
  6.1906 +    <ClInclude Include="..\..\asn.1\NegotiationOpen.h">
  6.1907 +      <Filter>Header Files</Filter>
  6.1908 +    </ClInclude>
  6.1909 +    <ClInclude Include="..\..\asn.1\NegotiationRequest.h">
  6.1910 +      <Filter>Header Files</Filter>
  6.1911 +    </ClInclude>
  6.1912 +    <ClInclude Include="..\..\asn.1\NegotiationRequestGrouped.h">
  6.1913 +      <Filter>Header Files</Filter>
  6.1914 +    </ClInclude>
  6.1915 +    <ClInclude Include="..\..\asn.1\OCTET_STRING.h">
  6.1916 +      <Filter>Header Files</Filter>
  6.1917 +    </ClInclude>
  6.1918 +    <ClInclude Include="..\..\asn.1\OwnKeysOfferer.h">
  6.1919 +      <Filter>Header Files</Filter>
  6.1920 +    </ClInclude>
  6.1921 +    <ClInclude Include="..\..\asn.1\OwnKeysRequester.h">
  6.1922 +      <Filter>Header Files</Filter>
  6.1923 +    </ClInclude>
  6.1924 +    <ClInclude Include="..\..\asn.1\per_decoder.h">
  6.1925 +      <Filter>Header Files</Filter>
  6.1926 +    </ClInclude>
  6.1927 +    <ClInclude Include="..\..\asn.1\per_encoder.h">
  6.1928 +      <Filter>Header Files</Filter>
  6.1929 +    </ClInclude>
  6.1930 +    <ClInclude Include="..\..\asn.1\per_opentype.h">
  6.1931 +      <Filter>Header Files</Filter>
  6.1932 +    </ClInclude>
  6.1933 +    <ClInclude Include="..\..\asn.1\per_support.h">
  6.1934 +      <Filter>Header Files</Filter>
  6.1935 +    </ClInclude>
  6.1936 +    <ClInclude Include="..\..\asn.1\PrintableString.h">
  6.1937 +      <Filter>Header Files</Filter>
  6.1938 +    </ClInclude>
  6.1939 +    <ClInclude Include="..\..\asn.1\PString.h">
  6.1940 +      <Filter>Header Files</Filter>
  6.1941 +    </ClInclude>
  6.1942 +    <ClInclude Include="..\..\asn.1\Rollback.h">
  6.1943 +      <Filter>Header Files</Filter>
  6.1944 +    </ClInclude>
  6.1945 +    <ClInclude Include="..\..\asn.1\Sync.h">
  6.1946 +      <Filter>Header Files</Filter>
  6.1947 +    </ClInclude>
  6.1948 +    <ClInclude Include="..\..\asn.1\SynchronizeGroupKeys.h">
  6.1949 +      <Filter>Header Files</Filter>
  6.1950 +    </ClInclude>
  6.1951 +    <ClInclude Include="..\..\asn.1\TID.h">
  6.1952 +      <Filter>Header Files</Filter>
  6.1953 +    </ClInclude>
  6.1954 +    <ClInclude Include="..\..\asn.1\UTF8String.h">
  6.1955 +      <Filter>Header Files</Filter>
  6.1956 +    </ClInclude>
  6.1957 +    <ClInclude Include="..\..\asn.1\Version.h">
  6.1958 +      <Filter>Header Files</Filter>
  6.1959 +    </ClInclude>
  6.1960 +    <ClInclude Include="..\..\asn.1\xer_decoder.h">
  6.1961 +      <Filter>Header Files</Filter>
  6.1962 +    </ClInclude>
  6.1963 +    <ClInclude Include="..\..\asn.1\xer_encoder.h">
  6.1964 +      <Filter>Header Files</Filter>
  6.1965 +    </ClInclude>
  6.1966 +    <ClInclude Include="..\..\asn.1\xer_support.h">
  6.1967 +      <Filter>Header Files</Filter>
  6.1968 +    </ClInclude>
  6.1969    </ItemGroup>
  6.1970  </Project>
  6.1971 \ No newline at end of file
     7.1 --- a/build-windows/pEpEngine.vcxproj	Mon Apr 13 13:08:13 2020 +0200
     7.2 +++ b/build-windows/pEpEngine.vcxproj	Tue Jul 07 11:53:12 2020 +0200
     7.3 @@ -139,6 +139,7 @@
     7.4      <ClCompile Include="..\src\etpan_mime.c" />
     7.5      <ClCompile Include="..\src\growing_buf.c" />
     7.6      <ClCompile Include="..\src\identity_list.c" />
     7.7 +    <ClCompile Include="..\src\internal_format.c" />
     7.8      <ClCompile Include="..\src\keymanagement.c" />
     7.9      <ClCompile Include="..\src\keyreset_command.c" />
    7.10      <ClCompile Include="..\src\KeySync_fsm.c" />
    7.11 @@ -180,6 +181,7 @@
    7.12      <ClInclude Include="..\src\fsm_common.h" />
    7.13      <ClInclude Include="..\src\growing_buf.h" />
    7.14      <ClInclude Include="..\src\identity_list.h" />
    7.15 +    <ClInclude Include="..\src\internal_format.h" />
    7.16      <ClInclude Include="..\src\keymanagement.h" />
    7.17      <ClInclude Include="..\src\KeySync_fsm.h" />
    7.18      <ClInclude Include="..\src\key_reset.h" />
    7.19 @@ -222,6 +224,9 @@
    7.20        <Project>{9a67164d-b8f8-4601-a24b-28afe774d41c}</Project>
    7.21      </ProjectReference>
    7.22    </ItemGroup>
    7.23 +  <ItemGroup>
    7.24 +    <None Include="generate_code.cmd" />
    7.25 +  </ItemGroup>
    7.26    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
    7.27    <ImportGroup Label="ExtensionTargets" />
    7.28  </Project>
    7.29 \ No newline at end of file
     8.1 --- a/build-windows/pEpEngine.vcxproj.filters	Mon Apr 13 13:08:13 2020 +0200
     8.2 +++ b/build-windows/pEpEngine.vcxproj.filters	Tue Jul 07 11:53:12 2020 +0200
     8.3 @@ -126,6 +126,9 @@
     8.4      <ClCompile Include="..\src\distribution_codec.c">
     8.5        <Filter>Quelldateien</Filter>
     8.6      </ClCompile>
     8.7 +    <ClCompile Include="..\src\internal_format.c">
     8.8 +      <Filter>Quelldateien</Filter>
     8.9 +    </ClCompile>
    8.10    </ItemGroup>
    8.11    <ItemGroup>
    8.12      <ClInclude Include="..\src\keymanagement.h">
    8.13 @@ -266,8 +269,16 @@
    8.14      <ClInclude Include="..\src\sync_codec.h">
    8.15        <Filter>Headerdateien</Filter>
    8.16      </ClInclude>
    8.17 +    <ClInclude Include="..\src\internal_format.h">
    8.18 +      <Filter>Headerdateien</Filter>
    8.19 +    </ClInclude>
    8.20    </ItemGroup>
    8.21    <ItemGroup>
    8.22      <Text Include="..\LICENSE.txt" />
    8.23    </ItemGroup>
    8.24 +  <ItemGroup>
    8.25 +    <None Include="generate_code.cmd">
    8.26 +      <Filter>Quelldateien</Filter>
    8.27 +    </None>
    8.28 +  </ItemGroup>
    8.29  </Project>
    8.30 \ No newline at end of file
     9.1 --- a/clean_sync_leftovers.sh	Mon Apr 13 13:08:13 2020 +0200
     9.2 +++ b/clean_sync_leftovers.sh	Tue Jul 07 11:53:12 2020 +0200
     9.3 @@ -6,5 +6,5 @@
     9.4  cd ..
     9.5  branch=`hg branch`
     9.6  if [ "$branch" = "sync" ]; then
     9.7 -    rm src/KeySync_fsm.c src/KeySync_fsm.h src/Sync_actions.c src/Sync_event.c src/Sync_event.h src/Sync_func.c src/Sync_func.h src/Sync_impl.c src/Sync_impl.h src/sync_codec.c src/sync_codec.h
     9.8 +    rm -f src/TrustSync_fsm.c src/TrustSync_fsm.h src/KeySync_fsm.c src/KeySync_fsm.h src/Sync_actions.c src/Sync_event.c src/Sync_event.h src/Sync_func.c src/Sync_func.h src/Sync_impl.c src/Sync_impl.h src/sync_codec.c src/sync_codec.h
     9.9  fi	
    10.1 --- a/doc/build-fedora.md	Mon Apr 13 13:08:13 2020 +0200
    10.2 +++ b/doc/build-fedora.md	Tue Jul 07 11:53:12 2020 +0200
    10.3 @@ -48,7 +48,6 @@
    10.4  mkdir -p ~/code/pep-engine
    10.5  hg clone https://pep.foundation/dev/repos/pEpEngine/ ~/code/pep-engine
    10.6  cd ~/code/pep-engine
    10.7 -hg update sync
    10.8  mkdir ~/code/pep-engine/build
    10.9  ~~~
   10.10  
    11.1 --- a/doc/build-macos.md	Mon Apr 13 13:08:13 2020 +0200
    11.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.3 @@ -1,161 +0,0 @@
    11.4 -<!-- Copyright 2015-2017, pEp foundation, Switzerland
    11.5 -This file is part of the pEp Engine
    11.6 -This file may be used under the terms of the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) License
    11.7 -See CC_BY-SA.txt -->
    11.8 -
    11.9 -# Build instructions for macOS Sierra
   11.10 -
   11.11 -# Installing packaged dependencies
   11.12 -You will find instructions for using either Macports or Homebrew below to install the compile-time dependencies.
   11.13 -
   11.14 -## MacPorts
   11.15 -Install MacPorts according to the instructions found [here](https://www.macports.org/install.php).
   11.16 -Ensure that Macports' binary paths (`/opt/local/bin` and `/opt/local/sbin`) are in your `PATH` environment variable.
   11.17 -
   11.18 -~~~
   11.19 -# general
   11.20 -sudo port install mercurial
   11.21 -# YML2
   11.22 -sudo port install py27-lxml
   11.23 -# libetpan
   11.24 -sudo port install git autoconf automake libtool
   11.25 -# asn1c
   11.26 -sudo port install asn1c
   11.27 -# engine
   11.28 -sudo port install gpgme
   11.29 -~~~
   11.30 -
   11.31 -Ensure that `python` is Python 2.7:
   11.32 -
   11.33 -~~~
   11.34 -sudo port select python python27
   11.35 -~~~
   11.36 -
   11.37 -## Homebrew
   11.38 -Install Homebrew according to the instructions found [here](https://docs.brew.sh/Installation.html).
   11.39 -Ensure that Homebrew's binary path (`/usr/local/bin`) is in your `PATH` environment variable.
   11.40 -
   11.41 -~~~
   11.42 -# general
   11.43 -brew install mercurial
   11.44 -# YML2
   11.45 -# If you don't have pip with your Python 2 distribution, you can install it with brew
   11.46 -brew install python
   11.47 -pip2 install --user lxml
   11.48 -# libetpan
   11.49 -brew install git autoconf automake libtool
   11.50 -# asn1c
   11.51 -brew install asn1c
   11.52 -# engine
   11.53 -brew install gpgme
   11.54 -~~~
   11.55 -
   11.56 -# Installing unpackaged dependencies
   11.57 -## YML2
   11.58 -To check if lxml is properly installed, you can use this lxml "hello world" command:
   11.59 -
   11.60 -~~~
   11.61 -python2 -c 'from lxml import etree; root = etree.Element("root"); print(root.tag)'
   11.62 -~~~
   11.63 -
   11.64 -It should generate the following output:
   11.65 -
   11.66 -~~~
   11.67 -root
   11.68 -~~~
   11.69 -
   11.70 -~~~
   11.71 -mkdir -p ~/code/yml2
   11.72 -hg clone https://pep.foundation/dev/repos/yml2/ ~/code/yml2
   11.73 -~~~
   11.74 -
   11.75 -## libetpan
   11.76 -pEp Engine requires libetpan with a set of patches that have not been upstreamed yet.
   11.77 -
   11.78 -~~~
   11.79 -mkdir -p ~/code/libetpan
   11.80 -git clone https://github.com/fdik/libetpan ~/code/libetpan
   11.81 -cd ~/code/libetpan
   11.82 -mkdir ~/code/libetpan/build
   11.83 -./autogen.sh --prefix="$HOME/code/libetpan/build"
   11.84 -make
   11.85 -make install
   11.86 -~~~
   11.87 -
   11.88 -## GPGME
   11.89 -The MacPorts-packaged GPGME links to a version of GNU libiconv that has files in the same include/library paths as GPGME. This version of libiconv must not be visible to the linker when the pEp Engine is build or run.
   11.90 -
   11.91 -Thus the files of the GPGME distribution will have to be manually copied to separate include/library folders, so that no include or library paths used for building the pEp Engine contains files of MacPorts' libiconv distribution.
   11.92 -
   11.93 -~~~
   11.94 -mkdir -p ~/code/gpgme/build/include
   11.95 -cp /opt/local/include/gpg*.h ~/code/gpgme/build/include
   11.96 -mkdir -p ~/code/gpgme/build/lib
   11.97 -cp -r /opt/local/lib/libgpg* ~/code/gpgme/build/lib
   11.98 -~~~
   11.99 -
  11.100 -It's of course possible to skip MacPort's version, and use a self-compiled GPGME/GPG. The default build configuration assumes this case, and assumes you have installed your GPGME with `$(HOME)` as your prefix.
  11.101 -
  11.102 -# pEp Engine
  11.103 -
  11.104 -~~~
  11.105 -mkdir -p ~/code/pep-engine
  11.106 -hg clone https://pep.foundation/dev/repos/pEpEngine/ ~/code/pep-engine
  11.107 -cd ~/code/pep-engine
  11.108 -mkdir ~/code/pep-engine/build
  11.109 -~~~
  11.110 -
  11.111 -Edit the build configuration to your needs in `Makefile.conf`, or create a `local.conf` that sets any of the make variables documented in `Makefile.conf`. All the default values for the build configuration variables on each platform are documented in `Makefile.conf`.
  11.112 -
  11.113 -If a dependency is not found in your system's default include or library paths, you will have to specify the according paths in a make variable. Typically, this has to be done at least for YML2, and libetpan.
  11.114 -
  11.115 -For a more detailed explanation of the mechanics of these build configuration files, and overriding defaults, see the comments in `Makefile.conf`.
  11.116 -
  11.117 -Below is a sample `./local.conf` file, for orientation.
  11.118 -
  11.119 -~~~
  11.120 -PREFIX=$(HOME)/code/engine/build
  11.121 -PER_MACHINE_DIRECTORY=$(PREFIX)/share/pEp
  11.122 -
  11.123 -YML2_PATH=$(HOME)/code/yml2
  11.124 -
  11.125 -ETPAN_LIB=-L$(HOME)/code/libetpan/build/lib
  11.126 -ETPAN_INC=-I$(HOME)/code/libetpan/build/include
  11.127 -
  11.128 -GPGME_LIB=-L$(HOME)/lib
  11.129 -GPGME_INC=-I$(HOME)/include
  11.130 -~~~
  11.131 -
  11.132 -The engine is built as follows:
  11.133 -
  11.134 -~~~
  11.135 -make all
  11.136 -make db
  11.137 -~~~
  11.138 -
  11.139 -If your build fails with an error message similar to the following:
  11.140 -
  11.141 -~~~
  11.142 -  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/locale.py", line 477, in _parse_localename
  11.143 -    raise ValueError, 'unknown locale: %s' % localename
  11.144 -ValueError: unknown locale: UTF-8
  11.145 -~~~
  11.146 -
  11.147 -or any other locale-related Python error, make sure Python does not have any locale-related environment variables set.
  11.148 -Usually, `unset LC_CTYPE` is sufficient to take care of the problem, but it depends on your macOS's regional and language settings and which terminal emulator you use.
  11.149 -This is a bug in Python, see [https://bugs.python.org/issue18378#msg215215](https://bugs.python.org/issue18378#msg215215).
  11.150 -
  11.151 -The unit tests can be run without the engine library being installed, however `system.db` must be installed:
  11.152 -
  11.153 -~~~
  11.154 -make -C db install
  11.155 -~~~
  11.156 -
  11.157 -Since `system.db` rarely changes, its installation is not needed for every build.
  11.158 -
  11.159 -Tests can be compiled and executed with the following commands:
  11.160 -
  11.161 -~~~
  11.162 -make -C test compile
  11.163 -make test
  11.164 -~~~
    12.1 --- a/doc/build-netpgp.md	Mon Apr 13 13:08:13 2020 +0200
    12.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.3 @@ -1,43 +0,0 @@
    12.4 -# Using NetPGP instead of GnuPG
    12.5 -## Prepare
    12.6 -
    12.7 -Get OpenSSL:
    12.8 -curl -O https://www.openssl.org/source/openssl-1.1.0f.tar.gz
    12.9 -
   12.10 -Build it using the openssl-for-ios build script:
   12.11 -git clone https://github.com/sinofool/build-openssl-ios/ .
   12.12 -
   12.13 -
   12.14 -
   12.15 - and build/install it as shared library.
   12.16 -
   12.17 -```
   12.18 -wget https://www.openssl.org/source/old/1.0.1/openssl-1.0.1u.tar.gz
   12.19 -tar xvfz openssl-1.0.1u.tar.gz
   12.20 -cd openssl-1.0.1u
   12.21 -./Configure darwin64-x86_64-cc --prefix=$HOME shared
   12.22 -make install
   12.23 -```
   12.24 -
   12.25 -Get and autoconf NetPGP
   12.26 -
   12.27 -```
   12.28 -cd $SRC
   12.29 -hg clone https://pep.foundation/dev/repos/netpgp-et/
   12.30 -cd netpgp-et
   12.31 -autoreconf -i
   12.32 -```
   12.33 -
   12.34 -## Build
   12.35 -
   12.36 -Important : LDFLAGS is set to help finding OpenSSL shared lib. If not set,
   12.37 -system's default libcrypto may silently be used instead, causing memory
   12.38 -corruption or crash at runtime.
   12.39 -
   12.40 -```
   12.41 -mkdir netpgp_debug
   12.42 -cd netpgp_debug
   12.43 -$SRC/netpgp-et/configure --with-openssl=$HOME --prefix=$HOME CPPFLAGS=-DDEBUG CXXFLAGS="-g -O0" LDFLAGS="-L${HOME}/lib"
   12.44 -make
   12.45 -make install
   12.46 -```
    13.1 --- a/doc/readme.md	Mon Apr 13 13:08:13 2020 +0200
    13.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.3 @@ -1,58 +0,0 @@
    13.4 -<!-- Copyright 2015-2017, pEp foundation, Switzerland
    13.5 -This file is part of the pEp Engine
    13.6 -This file may be used under the terms of the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) License
    13.7 -See CC_BY-SA.txt -->
    13.8 -
    13.9 -# Information about the pEp Engine
   13.10 -
   13.11 -# Dependencies
   13.12 -The p≡p Engine depends on the following projects:
   13.13 -
   13.14 -- run-time dependencies
   13.15 -  - One of the following OpenPGP implementations:
   13.16 -    - GnuPG version 2.1.17 or later with GPGME (at least version 1.7.0) [https://gnupg.org/](https://gnupg.org/)
   13.17 -    - For platforms not supporting pinentry (e.g. Android) - GnuPG version 2.0.30 with GPGME version 1.6.0 (or later) [https://gnupg.org/](https://gnupg.org/)
   13.18 -    - a fork of NetPGP, [https://pep.foundation/dev/repos/netpgp-et/](https://pep.foundation/dev/repos/netpgp-et/)
   13.19 -    - Sequoia, which in turn requires:
   13.20 -      - Rust
   13.21 -      - libnettle
   13.22 -  - One of the following MIME libraries:
   13.23 -    - a fork of libetpan, [https://github.com/fdik/libetpan](https://github.com/fdik/libetpan)
   13.24 -    - pEpMIME
   13.25 -  - zlib, [http://zlib.net/](http://zlib.net/)
   13.26 -  - libcurl (Only with NetPGP), [https://curl.haxx.se/libcurl/](https://curl.haxx.se/libcurl/)
   13.27 -  - libuuid, [https://www.kernel.org/pub/linux/utils/util-linux/](https://www.kernel.org/pub/linux/utils/util-linux/)
   13.28 -  - SQLite, [https://sqlite.org](https://sqlite.org)
   13.29 -  - OpenSSL (Only with NetPGP), [https://www.openssl.org](https://www.openssl.org)
   13.30 -- compile-time dependencies
   13.31 -  - asn1c (version v0.9.28), [http://lionet.info/asn1c/blog/](http://lionet.info/asn1c/blog/)
   13.32 -  - yml2, [https://fdik.org/yml//toolchain](https://fdik.org/yml//toolchain)
   13.33 -    - Python 3
   13.34 -    - LXML
   13.35 -  - One of the following build systems:
   13.36 -    - GNU make (on Linux and macOS)
   13.37 -    - MSBuild distributed with Microsoft Visual Studio 2015 (on Windows)
   13.38 -  - One of the following compilers for C and C++:
   13.39 -    - GNU GCC (on Linux)
   13.40 -    - Apple "clang" LLVM (on MacOS)
   13.41 -    - Microsoft MSVC/MSVC++ distributed with Microsoft Visual Studio 2015 (on Windows)
   13.42 -  - A script for compiling OpenSSL for iOS, [https://github.com/sinofool/build-openssl-ios/](https://github.com/sinofool/build-openssl-ios/)
   13.43 -  - binutils
   13.44 -
   13.45 -# The pEp Engine's databases
   13.46 -The p≡p Engine uses two databases:
   13.47 -
   13.48 -- the management database
   13.49 -  - `~/.pEp_management` on \*NIX
   13.50 -  - `%LOCALAPPDATA%\pEp\management.db` on Windows
   13.51 -- the Trustword database
   13.52 -  - `/usr/local/share/system.db` on \*NIX
   13.53 -  - `%ALLUSERSPROFILE%\pEp\system.db` on Windows
   13.54 -
   13.55 -The management db is created by the first call of `init()` of p≡p Engine.
   13.56 -It does not need to be created manually.
   13.57 -`system.db` is created by using the DDL in `db/create_system_db.sql`; the database content is created by `db/dic2csv.py` out of hunspell's dictionary packages (or something similar) and then imported using `sqlite3`'s `.import` command.
   13.58 -Dictionary files for different languages are part of the p≡p Engine source distribution.
   13.59 -
   13.60 -You can test the Trustwords in `system.db` using `db/trustwords.py`.
   13.61 -Both Python tools have a `--help` switch.
    14.1 --- a/doc/testing.md	Mon Apr 13 13:08:13 2020 +0200
    14.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.3 @@ -1,2 +0,0 @@
    14.4 -# Testing
    14.5 -For the documentation of the tests, see `test/README.md`
    15.1 --- a/src/Makefile	Mon Apr 13 13:08:13 2020 +0200
    15.2 +++ b/src/Makefile	Tue Jul 07 11:53:12 2020 +0200
    15.3 @@ -100,7 +100,7 @@
    15.4  	   timestamp.h identity_list.h bloblist.h stringpair.h message.h mime.h \
    15.5  	   cryptotech.h sync_api.h blacklist.h pEp_string.h openpgp_compat.h mime.h \
    15.6  	   labeled_int_list.h key_reset.h base64.h sync_codec.h distribution_codec.h \
    15.7 -	   status_to_string.h aux_mime_msg.h keyreset_command.h ../asn.1/*.h \
    15.8 +	   status_to_string.h aux_mime_msg.h keyreset_command.h platform.h platform_unix.h ../asn.1/*.h \
    15.9   	   $(PREFIX)/include/pEp/
   15.10  
   15.11  install: $(TARGET) install_headers
    16.1 --- a/src/aux_mime_msg.c	Mon Apr 13 13:08:13 2020 +0200
    16.2 +++ b/src/aux_mime_msg.c	Tue Jul 07 11:53:12 2020 +0200
    16.3 @@ -73,7 +73,7 @@
    16.4      message* dec_msg = NULL;
    16.5      *mime_plaintext = NULL;
    16.6  
    16.7 -    status = mime_decode_message(mimetext, size, &tmp_msg);
    16.8 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
    16.9      if (status != PEP_STATUS_OK)
   16.10          goto pEp_error;
   16.11  
   16.12 @@ -120,7 +120,7 @@
   16.13      }
   16.14  
   16.15      if (*flags & PEP_decrypt_flag_src_modified) {
   16.16 -        _mime_encode_message_internal(tmp_msg, false, modified_src, true, false);
   16.17 +        mime_encode_message(tmp_msg, false, modified_src, false);
   16.18          if (!modified_src) {
   16.19              *flags &= (~PEP_decrypt_flag_src_modified);
   16.20              decrypt_status = PEP_CANNOT_REENCRYPT; // Because we couldn't return it, I guess.
   16.21 @@ -128,7 +128,7 @@
   16.22      }
   16.23  
   16.24      // FIXME: test with att
   16.25 -    status = _mime_encode_message_internal(dec_msg, false, mime_plaintext, true, false);
   16.26 +    status = mime_encode_message(dec_msg, false, mime_plaintext, false);
   16.27  
   16.28      if (status == PEP_STATUS_OK)
   16.29      {
   16.30 @@ -161,7 +161,7 @@
   16.31      message* enc_msg = NULL;
   16.32      message* ret_msg = NULL;                             
   16.33  
   16.34 -    status = mime_decode_message(mimetext, size, &tmp_msg);
   16.35 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
   16.36      if (status != PEP_STATUS_OK)
   16.37          goto pEp_error;
   16.38  
   16.39 @@ -217,12 +217,10 @@
   16.40          goto pEp_error;
   16.41      }
   16.42      
   16.43 -    tmp_status = _mime_encode_message_internal(
   16.44 -                                ret_msg, 
   16.45 -                                false, 
   16.46 -                                mime_ciphertext, 
   16.47 -                                false, 
   16.48 -                                false);
   16.49 +    tmp_status = mime_encode_message(ret_msg, 
   16.50 +                                     false, 
   16.51 +                                     mime_ciphertext, 
   16.52 +                                     false);
   16.53      
   16.54      if (tmp_status != PEP_STATUS_OK)
   16.55          status = tmp_status;
   16.56 @@ -250,7 +248,7 @@
   16.57      message* tmp_msg = NULL;
   16.58      message* enc_msg = NULL;
   16.59  
   16.60 -    status = mime_decode_message(mimetext, size, &tmp_msg);
   16.61 +    status = mime_decode_message(mimetext, size, &tmp_msg, NULL);
   16.62      if (status != PEP_STATUS_OK)
   16.63          goto pEp_error;
   16.64  
   16.65 @@ -271,7 +269,7 @@
   16.66          goto pEp_error;
   16.67      }
   16.68  
   16.69 -    status = mime_encode_message(enc_msg, false, mime_ciphertext);
   16.70 +    status = mime_encode_message(enc_msg, false, mime_ciphertext, false);
   16.71  
   16.72  pEp_error:
   16.73      free_message(tmp_msg);
    17.1 --- a/src/base64.c	Mon Apr 13 13:08:13 2020 +0200
    17.2 +++ b/src/base64.c	Tue Jul 07 11:53:12 2020 +0200
    17.3 @@ -85,18 +85,22 @@
    17.4          return NULL;
    17.5      
    17.6      trim_end(input, &length);
    17.7 -        
    17.8 +    
    17.9 +    void* blobby = NULL;
   17.10 +    
   17.11      const char* input_curr;
   17.12      input_curr = input;
   17.13      const char* input_end = input_curr + length;
   17.14      length = subtract_whitespace(input, length);
   17.15      size_t final_length = (length / 4) * 3;
   17.16  
   17.17 -    // padded -- FIXME: whitespace in between ==!!!! 
   17.18 -    if (*(input_end - 1) == '=') {
   17.19 +    // padded -- FIXME: whitespace in between ==!!!!
   17.20 +    if (final_length && *(input_end - 1) == '=') {
   17.21          final_length -= 1;
   17.22          
   17.23 -        if (*(input_end - 2) == '=')
   17.24 +        // if final length is now decreased by 1 and greater than 0,
   17.25 +        // we know there's a char at (input_end - 2).
   17.26 +        if (final_length && *(input_end - 2) == '=')
   17.27              final_length -=1;
   17.28      }
   17.29      else {
   17.30 @@ -115,7 +119,11 @@
   17.31                  return NULL;
   17.32          }
   17.33      }
   17.34 -    void* blobby = calloc(final_length, 1);
   17.35 +    
   17.36 +    if (!final_length)
   17.37 +        goto pEp_error;
   17.38 +        
   17.39 +    blobby = calloc(final_length, 1);
   17.40      char* blobby_curr = (char*)blobby;
   17.41  
   17.42      // if the last 1 or 2 bytes are padded, we do those after
   17.43 @@ -217,4 +225,3 @@
   17.44      free(blobby);
   17.45      return NULL;
   17.46  }    
   17.47 -
    18.1 --- a/src/baseprotocol.c	Mon Apr 13 13:08:13 2020 +0200
    18.2 +++ b/src/baseprotocol.c	Tue Jul 07 11:53:12 2020 +0200
    18.3 @@ -30,14 +30,26 @@
    18.4      if (!(msg && payload && size && type))
    18.5          return PEP_ILLEGAL_VALUE;
    18.6  
    18.7 -    bloblist_t *bl = bloblist_add(msg->attachments, payload, size,
    18.8 -            _base_type[type], "ignore_this_attachment.pEp");
    18.9 -    if (bl == NULL) {
   18.10 +    bloblist_t *bl;
   18.11 +
   18.12 +    switch (type) {
   18.13 +        case BASE_SYNC:
   18.14 +            bl = bloblist_add(msg->attachments, payload, size,
   18.15 +                    _base_type[type], "sync.pEp");
   18.16 +            break;
   18.17 +        case BASE_KEYRESET:
   18.18 +            bl = bloblist_add(msg->attachments, payload, size,
   18.19 +                    _base_type[type], "distribution.pEp");
   18.20 +            break;
   18.21 +        default:
   18.22 +            bl = bloblist_add(msg->attachments, payload, size,
   18.23 +                    _base_type[type], "ignore_this_attachment.pEp");
   18.24 +    }
   18.25 +
   18.26 +    if (bl == NULL)
   18.27          goto enomem;
   18.28 -    }
   18.29 -    else if (!msg->attachments) {
   18.30 +    else if (!msg->attachments)
   18.31          msg->attachments = bl;
   18.32 -    }
   18.33  
   18.34      if (fpr && fpr[0] != '\0') {
   18.35          char *sign;
   18.36 @@ -202,3 +214,60 @@
   18.37      free_stringlist(keylist);
   18.38      return status;
   18.39  }
   18.40 +
   18.41 +PEP_STATUS try_base_prepare_message(
   18.42 +        PEP_SESSION session,
   18.43 +        const pEp_identity *me,
   18.44 +        const pEp_identity *partner,
   18.45 +        base_protocol_type type,
   18.46 +        char *payload,
   18.47 +        size_t size,
   18.48 +        const char *fpr,
   18.49 +        message **result
   18.50 +    )
   18.51 +{
   18.52 +    PEP_STATUS status = PEP_STATUS_OK;
   18.53 +
   18.54 +    assert(session && session->messageToSend && session->notifyHandshake);
   18.55 +    assert(me);
   18.56 +    assert(partner);
   18.57 +    assert(payload);
   18.58 +    assert(size);
   18.59 +    assert(result);
   18.60 +    assert(type == BASE_SYNC || type == BASE_KEYRESET);
   18.61 +
   18.62 +    if (!(session && session->messageToSend && session->notifyHandshake))
   18.63 +        return PEP_ILLEGAL_VALUE;
   18.64 +
   18.65 +    if (!(me && partner && payload && size && result && type))
   18.66 +        return PEP_ILLEGAL_VALUE;
   18.67 +
   18.68 +    // https://dev.pep.foundation/Engine/MessageToSendPassphrase
   18.69 +
   18.70 +    if (session->curr_passphrase) {
   18.71 +        // first try with empty passphrase
   18.72 +        char *passphrase = session->curr_passphrase;
   18.73 +        session->curr_passphrase = NULL;
   18.74 +        status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
   18.75 +        session->curr_passphrase = passphrase;
   18.76 +        if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
   18.77 +            return status;
   18.78 +    }
   18.79 +
   18.80 +    do {
   18.81 +        // then try passphrases
   18.82 +        status = base_prepare_message(session, me, partner, type, payload, size, fpr, result);
   18.83 +        if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
   18.84 +            PEP_STATUS status2 = session->messageToSend(NULL);
   18.85 +            if (status2 == PEP_PASSPHRASE_REQUIRED || status2 == PEP_WRONG_PASSPHRASE) {
   18.86 +                pEp_identity *_me = identity_dup(me);
   18.87 +                if (!_me)
   18.88 +                    return PEP_OUT_OF_MEMORY;
   18.89 +                session->notifyHandshake(_me, NULL, SYNC_PASSPHRASE_REQUIRED);
   18.90 +            }
   18.91 +        }
   18.92 +    } while (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE);
   18.93 +
   18.94 +    return status;
   18.95 +}
   18.96 +
    19.1 --- a/src/baseprotocol.h	Mon Apr 13 13:08:13 2020 +0200
    19.2 +++ b/src/baseprotocol.h	Tue Jul 07 11:53:12 2020 +0200
    19.3 @@ -106,6 +106,22 @@
    19.4      );
    19.5  
    19.6  
    19.7 +// this is the internal function to be used by asynchronous network protocol
    19.8 +// implementations
    19.9 +//
   19.10 +// this function is calling messageToSend(NULL) in case there is a missing or wrong passphrase
   19.11 +
   19.12 +PEP_STATUS try_base_prepare_message(
   19.13 +        PEP_SESSION session,
   19.14 +        const pEp_identity *me,
   19.15 +        const pEp_identity *partner,
   19.16 +        base_protocol_type type,
   19.17 +        char *payload,
   19.18 +        size_t size,
   19.19 +        const char *fpr,
   19.20 +        message **result
   19.21 +    );
   19.22 +
   19.23  #ifdef __cplusplus
   19.24  }
   19.25  #endif
    20.1 --- a/src/cryptotech.h	Mon Apr 13 13:08:13 2020 +0200
    20.2 +++ b/src/cryptotech.h	Tue Jul 07 11:53:12 2020 +0200
    20.3 @@ -65,7 +65,8 @@
    20.4      );
    20.5  
    20.6  typedef PEP_STATUS (*import_key_t)(PEP_SESSION session, const char *key_data,
    20.7 -        size_t size, identity_list **private_keys);
    20.8 +        size_t size, identity_list **private_keys, stringlist_t** imported_keys,
    20.9 +        uint64_t* changed_key_index);
   20.10  
   20.11  typedef PEP_STATUS (*recv_key_t)(PEP_SESSION session, const char *pattern);
   20.12  
   20.13 @@ -133,4 +134,3 @@
   20.14  
   20.15  PEP_STATUS init_cryptotech(PEP_SESSION session, bool in_first);
   20.16  void release_cryptotech(PEP_SESSION session, bool out_last);
   20.17 -
    21.1 --- a/src/etpan_mime.c	Mon Apr 13 13:08:13 2020 +0200
    21.2 +++ b/src/etpan_mime.c	Tue Jul 07 11:53:12 2020 +0200
    21.3 @@ -324,8 +324,7 @@
    21.4          const char * mime_type,
    21.5          char * data,
    21.6          size_t length,
    21.7 -        bool transport_encode,
    21.8 -        bool set_attachment_forward_comment
    21.9 +        bool is_nf_message_attachment // non-forwarded msg as att
   21.10      )
   21.11  {
   21.12      char * disposition_name = NULL;
   21.13 @@ -373,7 +372,9 @@
   21.14  
   21.15      encoding = NULL;
   21.16  
   21.17 -    if (transport_encode) {
   21.18 +    bool already_ascii = !(must_chunk_be_encoded(data, length, true));
   21.19 +    
   21.20 +    if (!is_nf_message_attachment && !already_ascii) {
   21.21          encoding_type = MAILMIME_MECHANISM_BASE64;
   21.22          encoding = mailmime_mechanism_new(encoding_type, NULL);
   21.23          if (encoding == NULL)
   21.24 @@ -389,7 +390,7 @@
   21.25  
   21.26      stringpair_list_t* extra_params = NULL;
   21.27      
   21.28 -    if (set_attachment_forward_comment)
   21.29 +    if (is_nf_message_attachment)
   21.30          extra_params = new_stringpair_list(new_stringpair("forwarded", "no"));
   21.31      
   21.32      mime = part_new_empty(content, mime_fields, extra_params, 1);
   21.33 @@ -555,20 +556,37 @@
   21.34          const char *address
   21.35      )
   21.36  {
   21.37 +    assert(address);
   21.38 +    if (!address)
   21.39 +        return NULL;
   21.40 +
   21.41      struct mailimf_mailbox *mb = NULL;
   21.42      char *_name = NULL;
   21.43      char *_address = NULL;
   21.44  
   21.45 -    assert(address);
   21.46 -
   21.47      _name = name ? strdup(name) : strdup("");
   21.48      if (_name == NULL)
   21.49          goto enomem;
   21.50  
   21.51 -    _address = strdup(address);
   21.52 -    if (_address == NULL)
   21.53 -        goto enomem;
   21.54 -
   21.55 +    char* at = strstr(address, "@");
   21.56 +    if (!at) {
   21.57 +        // Presumed URI
   21.58 +        int added_char_len = 6; // " " @URI 
   21.59 +        int new_addr_len = strlen(address) + added_char_len + 1;
   21.60 +        _address = calloc(new_addr_len, 1);
   21.61 +        if (_address == NULL)
   21.62 +            goto enomem;
   21.63 +        
   21.64 +        _address[0] = '"';
   21.65 +        strlcat(_address, address, new_addr_len);
   21.66 +        strlcat(_address, "\"@URI", new_addr_len);
   21.67 +    }
   21.68 +    else {
   21.69 +        _address = strdup(address);
   21.70 +        if (_address == NULL)
   21.71 +            goto enomem;
   21.72 +    }
   21.73 +            
   21.74      mb = mailimf_mailbox_new(_name, _address);
   21.75      assert(mb);
   21.76      if (mb == NULL)
   21.77 @@ -1005,7 +1023,7 @@
   21.78  
   21.79  static PEP_STATUS interpret_MIME(struct mailmime *mime,
   21.80                                   message *msg,
   21.81 -                                 bool* raise_msg_attachment);
   21.82 +                                 bool* has_possible_pEp_msg);
   21.83  
   21.84  // This function was rewritten to use in-memory buffers instead of
   21.85  // temporary files when the pgp/mime support was implemented for
   21.86 @@ -1063,8 +1081,7 @@
   21.87  static PEP_STATUS mime_attachment(
   21.88          bloblist_t *blob,
   21.89          struct mailmime **result,
   21.90 -        bool transport_encode,
   21.91 -        bool set_attachment_forward_comment
   21.92 +        bool is_nf_message_attachment // non-forwarded msg as att
   21.93      )
   21.94  {
   21.95      PEP_STATUS status = PEP_STATUS_OK;
   21.96 @@ -1086,11 +1103,8 @@
   21.97  
   21.98      pEp_rid_list_t* resource = parse_uri(blob->filename);
   21.99  
  21.100 -    bool already_ascii = !(must_chunk_be_encoded(blob->value, blob->size, true));
  21.101 -
  21.102      mime = get_file_part(resource, mime_type, blob->value, blob->size, 
  21.103 -                          (already_ascii ? false : transport_encode),
  21.104 -                          set_attachment_forward_comment);
  21.105 +                         is_nf_message_attachment);
  21.106      free_rid_list(resource);
  21.107      
  21.108      assert(mime);
  21.109 @@ -1109,12 +1123,23 @@
  21.110      return status;
  21.111  }
  21.112  
  21.113 +
  21.114 +// This ONLY deals with handling the body 
  21.115 +// content when html parts are present - thus,
  21.116 +// text/plain and text/html of the body, and 
  21.117 +// related inline attachments for the html 
  21.118 +// part. Non-inline attachments are handled 
  21.119 +// outside this call!!!!
  21.120 +//
  21.121 +// N.B. As a result, this will only touch the 
  21.122 +// "contained message" of pEp 2.x messages 
  21.123 +// on the initial encoding where it is turned 
  21.124 +// into attachment data!!
  21.125  static PEP_STATUS mime_html_text(
  21.126          const char *plaintext,
  21.127          const char *htmltext,
  21.128          bloblist_t *attachments,
  21.129 -        struct mailmime **result,
  21.130 -        bool transport_encode
  21.131 +        struct mailmime **result
  21.132      )
  21.133  {
  21.134      PEP_STATUS status = PEP_STATUS_OK;
  21.135 @@ -1129,33 +1154,50 @@
  21.136  
  21.137      *result = NULL;
  21.138  
  21.139 -    mime = part_multiple_new("multipart/alternative");
  21.140 -    assert(mime);
  21.141 -    if (mime == NULL)
  21.142 -        goto enomem;
  21.143 -
  21.144      pEp_rid_list_t* resource = NULL;
  21.145 +        
  21.146 +    bool already_ascii = false;
  21.147 +    int encoding_type = 0;    
  21.148 +    if (*plaintext != '\0') {
  21.149 +        mime = part_multiple_new("multipart/alternative");
  21.150 +        assert(mime);
  21.151 +        if (mime == NULL)
  21.152 +            goto enomem;
  21.153 +            
  21.154 +        // KB: pEpMIME transition comment - if we start getting 
  21.155 +        // underencoding errors here, the change to checking 
  21.156 +        // for ASCII and then encoding - or not - is one place 
  21.157 +        // to start looking.
  21.158 +        int pt_length = strlen(plaintext);
  21.159 +        already_ascii = !(must_chunk_be_encoded(plaintext, pt_length, true));                
  21.160 +        encoding_type = (already_ascii ? 0 : MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  21.161 +                
  21.162 +        submime = get_text_part(NULL, "text/plain", plaintext, 
  21.163 +                                pt_length,
  21.164 +                                encoding_type);
  21.165 +        
  21.166 +        // reset                        
  21.167 +        already_ascii = false;
  21.168 +        encoding_type = 0;
  21.169 +                                    
  21.170 +        free_rid_list(resource);
  21.171 +        resource = NULL;
  21.172 +        
  21.173 +        assert(submime);
  21.174 +        if (submime == NULL)
  21.175 +            goto enomem;
  21.176 +
  21.177 +        r = mailmime_smart_add_part(mime, submime);
  21.178 +        assert(r == MAILIMF_NO_ERROR);
  21.179 +        if (r == MAILIMF_ERROR_MEMORY) {
  21.180 +            goto enomem;
  21.181 +        }
  21.182 +        else {
  21.183 +            // mailmime_smart_add_part() takes ownership of submime
  21.184 +            submime = NULL;
  21.185 +        }
  21.186 +    }
  21.187      
  21.188 -    int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  21.189 -    submime = get_text_part(NULL, "text/plain", plaintext, strlen(plaintext),
  21.190 -            encoding_type);
  21.191 -    free_rid_list(resource);
  21.192 -    resource = NULL;
  21.193 -    
  21.194 -    assert(submime);
  21.195 -    if (submime == NULL)
  21.196 -        goto enomem;
  21.197 -
  21.198 -    r = mailmime_smart_add_part(mime, submime);
  21.199 -    assert(r == MAILIMF_NO_ERROR);
  21.200 -    if (r == MAILIMF_ERROR_MEMORY) {
  21.201 -        goto enomem;
  21.202 -    }
  21.203 -    else {
  21.204 -        // mailmime_smart_add_part() takes ownership of submime
  21.205 -        submime = NULL;
  21.206 -    }
  21.207 -
  21.208      bool inlined_attachments = false;
  21.209      
  21.210      bloblist_t* traversal_ptr = attachments;
  21.211 @@ -1175,60 +1217,88 @@
  21.212          if (submime == NULL)
  21.213              goto enomem;
  21.214  
  21.215 +        // This is where all of the html MIME stuff will go
  21.216          top_level_html_mime = submime;
  21.217          
  21.218 -        r = mailmime_smart_add_part(mime, top_level_html_mime);
  21.219 -        assert(r == MAILIMF_NO_ERROR);
  21.220 -        if (r == MAILIMF_ERROR_MEMORY) {
  21.221 -            goto enomem;
  21.222 -        }
  21.223 -        else {
  21.224 -            // mailmime_smart_add_part() takes ownership of submime
  21.225 -            submime = NULL;
  21.226 -        }
  21.227 +        if (!mime)
  21.228 +            mime = top_level_html_mime;
  21.229 +        else {    
  21.230 +            r = mailmime_smart_add_part(mime, top_level_html_mime);
  21.231 +            assert(r == MAILIMF_NO_ERROR);
  21.232 +            if (r == MAILIMF_ERROR_MEMORY) {
  21.233 +                goto enomem;
  21.234 +            }
  21.235 +            else {
  21.236 +                // mailmime_smart_add_part() takes ownership of submime
  21.237 +                submime = NULL;
  21.238 +            }
  21.239 +        }    
  21.240      }
  21.241      else {
  21.242 +        // Otherwise, html MIME stuff gets added to the top node 
  21.243 +        // - may be NULL if there's no multipart!
  21.244          top_level_html_mime = mime;
  21.245      }
  21.246  
  21.247  //    resource = new_rid_node(PEP_RID_FILENAME, "msg.html");
  21.248 -    submime = get_text_part(NULL, "text/html", htmltext, strlen(htmltext),
  21.249 -            encoding_type);
  21.250 +    int ht_length = strlen(htmltext);
  21.251 +    already_ascii = !(must_chunk_be_encoded(htmltext, ht_length, true));                
  21.252 +    encoding_type = (already_ascii ? 0 : MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  21.253 +            
  21.254 +    submime = get_text_part(NULL, "text/html", htmltext, 
  21.255 +                            ht_length,
  21.256 +                            encoding_type);
  21.257 +
  21.258      free_rid_list(resource);
  21.259      resource = NULL;
  21.260      
  21.261      assert(submime);
  21.262      if (submime == NULL)
  21.263          goto enomem;
  21.264 -
  21.265 -    r = mailmime_smart_add_part(top_level_html_mime, submime);
  21.266 -    assert(r == MAILIMF_NO_ERROR);
  21.267 -    if (r == MAILIMF_ERROR_MEMORY)
  21.268 -        goto enomem;
  21.269 -    else {
  21.270 -        // mailmime_smart_add_part() takes ownership of submime
  21.271 +        
  21.272 +    // IF there are no inlined attachments AND mime is NULL, then 
  21.273 +    // we just have an HTML body here and won't need to 
  21.274 +    // process inlined attachments - submime will actually be 
  21.275 +    // the mime root of from this function, at least.    
  21.276 +
  21.277 +    if (!top_level_html_mime) {
  21.278 +        mime = submime;
  21.279          submime = NULL;
  21.280      }
  21.281 -
  21.282 -    bloblist_t *_a;
  21.283 -    for (_a = attachments; _a != NULL; _a = _a->next) {
  21.284 -        if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  21.285 -            continue;
  21.286 -        status = mime_attachment(_a, &submime, transport_encode, false);
  21.287 -        if (status != PEP_STATUS_OK)
  21.288 -            return PEP_UNKNOWN_ERROR; // FIXME
  21.289 -
  21.290 +    else {    
  21.291          r = mailmime_smart_add_part(top_level_html_mime, submime);
  21.292          assert(r == MAILIMF_NO_ERROR);
  21.293 -        if (r == MAILIMF_ERROR_MEMORY) {
  21.294 +        if (r == MAILIMF_ERROR_MEMORY)
  21.295              goto enomem;
  21.296 -        }
  21.297          else {
  21.298              // mailmime_smart_add_part() takes ownership of submime
  21.299              submime = NULL;
  21.300          }
  21.301 -    }
  21.302 -
  21.303 +
  21.304 +        bloblist_t *_a;
  21.305 +
  21.306 +        // This will never have an embedded pEp message attachment 
  21.307 +        // sent for encoding here, so we don't need to pass down 
  21.308 +        // "(don't) transport encode this" info. If it's here and 
  21.309 +        // it's not an ASCII "text/*" attachment, it'll get encoded
  21.310 +        for (_a = attachments; _a != NULL; _a = _a->next) {
  21.311 +            if (_a->disposition != PEP_CONTENT_DISP_INLINE)
  21.312 +                continue;
  21.313 +            status = mime_attachment(_a, &submime, false);
  21.314 +            if (status != PEP_STATUS_OK)
  21.315 +                return PEP_UNKNOWN_ERROR; // FIXME
  21.316 +
  21.317 +            r = mailmime_smart_add_part(top_level_html_mime, submime);
  21.318 +            assert(r == MAILIMF_NO_ERROR);
  21.319 +            if (r == MAILIMF_ERROR_MEMORY) {
  21.320 +                goto enomem;
  21.321 +            }
  21.322 +            else {
  21.323 +                // mailmime_smart_add_part() takes ownership of submime
  21.324 +                submime = NULL;
  21.325 +            }
  21.326 +        }
  21.327 +    }    
  21.328      *result = mime;
  21.329      return PEP_STATUS_OK;
  21.330  
  21.331 @@ -1245,7 +1315,6 @@
  21.332  }
  21.333  
  21.334  
  21.335 -// FIXME: maybe need to add transport_encode field here
  21.336  static struct mailimf_mailbox * identity_to_mailbox(const pEp_identity *ident)
  21.337  {
  21.338      char *_username = NULL;
  21.339 @@ -1363,6 +1432,9 @@
  21.340      return NULL;
  21.341  }
  21.342  
  21.343 +// KB: This seems to be always called with "true",
  21.344 +//     but there was probably a reason for this. So 
  21.345 +//     leave it for now.
  21.346  static clist * stringlist_to_clist(stringlist_t *sl, bool transport_encode)
  21.347  {
  21.348      clist * cl = clist_new();
  21.349 @@ -1691,8 +1763,7 @@
  21.350          const message *msg,
  21.351          bool omit_fields,
  21.352          struct mailmime **result,
  21.353 -        bool transport_encode,
  21.354 -        bool set_attachment_forward_comment
  21.355 +        bool has_pEp_msg_attachment
  21.356      )
  21.357  {
  21.358      struct mailmime * mime = NULL;
  21.359 @@ -1700,13 +1771,13 @@
  21.360      int r;
  21.361      PEP_STATUS status;
  21.362      //char *subject;
  21.363 -    char *plaintext;
  21.364 +    const char *plaintext;
  21.365      char *htmltext;
  21.366  
  21.367      assert(msg);
  21.368      assert(result);
  21.369 -    
  21.370 -    //subject = (msg->shortmsg) ? msg->shortmsg : "pEp";  // not used, yet.
  21.371 +
  21.372 +    // * Process body content, including html's inlined attachments *
  21.373      plaintext = (msg->longmsg) ? msg->longmsg : "";
  21.374      htmltext = msg->longmsg_formatted;
  21.375  
  21.376 @@ -1714,23 +1785,37 @@
  21.377          /* first, we need to strip out the inlined attachments to ensure this
  21.378             gets set up correctly */
  21.379             
  21.380 -        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime,
  21.381 -                                transport_encode);
  21.382 +        // Note: this only, regardless of whether this is being done 
  21.383 +        // for the to-be-embedded message attachment generation or 
  21.384 +        // an encapsulating message which contains this, touches 
  21.385 +        // the body text of this input message. So transport encoding 
  21.386 +        // only refers to the body content here and inlined-attachments, and 
  21.387 +        // is decided WITHIN this function, not as an argument. 
  21.388 +        status = mime_html_text(plaintext, htmltext, msg->attachments, &mime);
  21.389                  
  21.390          if (status != PEP_STATUS_OK)
  21.391              goto pEp_error;
  21.392      }
  21.393 -    else {
  21.394 +    else { /* body content only consists of a plaintext block */
  21.395          pEp_rid_list_t* resource = NULL;
  21.396 +
  21.397 +        int pt_length = strlen(plaintext);
  21.398 +
  21.399          if (is_PGP_message_text(plaintext)) {
  21.400              resource = NULL;
  21.401 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  21.402 +            
  21.403 +            // So... I think we got overencoding here once, which would be a bug 
  21.404 +            // in libetpan, unless it had to do with whitespace. If removing
  21.405 +            // transport encoding as a calculation here somehow leads to overencoding,
  21.406 +            // either we or libetpan are doing something bad.
  21.407 +//            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_7BIT : 0);
  21.408              mime = get_text_part(resource, "application/octet-stream", plaintext,
  21.409 -                    strlen(plaintext), encoding_type);
  21.410 +                                 pt_length, MAILMIME_MECHANISM_7BIT);
  21.411          }
  21.412          else {
  21.413              resource = NULL;
  21.414 -            int encoding_type = (transport_encode ? MAILMIME_MECHANISM_QUOTED_PRINTABLE : 0);
  21.415 +            bool already_ascii = !(must_chunk_be_encoded(plaintext, pt_length, true));                
  21.416 +            int encoding_type = (already_ascii ? MAILMIME_MECHANISM_7BIT : MAILMIME_MECHANISM_QUOTED_PRINTABLE);
  21.417              mime = get_text_part(resource, "text/plain", plaintext, strlen(plaintext),
  21.418                      encoding_type);
  21.419          }
  21.420 @@ -1741,10 +1826,21 @@
  21.421              goto enomem;
  21.422      }
  21.423  
  21.424 +    /* Body content processed, now process normal attachments */
  21.425 +    
  21.426      bool normal_attachments = false;
  21.427      
  21.428      bloblist_t* traversal_ptr = msg->attachments;
  21.429      
  21.430 +    // If there were any inline attachments, they should have 
  21.431 +    // been stripped out in mime_html_text and dealt with. 
  21.432 +    // I'm not entirely sure what the alternative case 
  21.433 +    // is here. But basically, if there are any non-inlined 
  21.434 +    // attachments to deal with, this is designed to 
  21.435 +    // make sure we process them. So flag it for 
  21.436 +    // "hey, Bob, you got some regular attachments here"
  21.437 +    // so Bob (obviously, the MIME engine is called Bob)
  21.438 +    // can do the right thing in the next block.
  21.439      while (traversal_ptr) {
  21.440          if (traversal_ptr->disposition != PEP_CONTENT_DISP_INLINE) {
  21.441              normal_attachments = true;
  21.442 @@ -1773,13 +1869,18 @@
  21.443          bloblist_t *_a;
  21.444          bool first_one = true;
  21.445          
  21.446 +        // Go through the non-inline attachments and add em.
  21.447          for (_a = msg->attachments; _a != NULL; _a = _a->next) {
  21.448  
  21.449              if (_a->disposition == PEP_CONTENT_DISP_INLINE)
  21.450                  continue;
  21.451  
  21.452 -            status = mime_attachment(_a, &submime, transport_encode,
  21.453 -                                     (first_one && set_attachment_forward_comment));                         
  21.454 +            // solely for readability.
  21.455 +            bool is_pEp_msg_attachment = (first_one && has_pEp_msg_attachment);
  21.456 +
  21.457 +            status = mime_attachment(_a, &submime, 
  21.458 +                                     is_pEp_msg_attachment);                         
  21.459 +
  21.460              if (status != PEP_STATUS_OK)
  21.461                  goto pEp_error;
  21.462              
  21.463 @@ -1891,12 +1992,11 @@
  21.464      return status;
  21.465  }
  21.466  
  21.467 -PEP_STATUS _mime_encode_message_internal(
  21.468 +DYNAMIC_API PEP_STATUS mime_encode_message(
  21.469          const message * msg,
  21.470          bool omit_fields,
  21.471          char **mimetext,
  21.472 -        bool transport_encode,
  21.473 -        bool set_attachment_forward_comment
  21.474 +        bool has_pEp_msg_attachment
  21.475      )
  21.476  {
  21.477      PEP_STATUS status = PEP_STATUS_OK;
  21.478 @@ -1916,12 +2016,12 @@
  21.479  
  21.480      switch (msg->enc_format) {
  21.481          case PEP_enc_none:
  21.482 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode, set_attachment_forward_comment);
  21.483 +            status = mime_encode_message_plain(msg, omit_fields, &mime, has_pEp_msg_attachment);
  21.484              break;
  21.485  
  21.486 -        // I'm presuming we should hardcore ignoring set_attachment_forward_comment here...
  21.487 +        // I'm presuming we should hardcore ignoring has_pEp_msg_attachment here...
  21.488          case PEP_enc_inline:
  21.489 -            status = mime_encode_message_plain(msg, omit_fields, &mime, transport_encode, false);
  21.490 +            status = mime_encode_message_plain(msg, omit_fields, &mime, false);
  21.491              break;
  21.492  
  21.493          case PEP_enc_S_MIME:
  21.494 @@ -1988,6 +2088,7 @@
  21.495  static pEp_identity *mailbox_to_identity(const struct mailimf_mailbox * mb)
  21.496  {
  21.497      char *username = NULL;
  21.498 +    char *address = NULL;
  21.499  
  21.500      assert(mb);
  21.501      assert(mb->mb_addr_spec);
  21.502 @@ -2003,14 +2104,30 @@
  21.503              goto enomem;
  21.504      }
  21.505  
  21.506 -    pEp_identity *ident = new_identity(mb->mb_addr_spec, NULL, NULL, username);
  21.507 +    const char* raw_addr = mb->mb_addr_spec;
  21.508 +    if (raw_addr && raw_addr[0] == '"') {
  21.509 +        int addr_len = strlen(raw_addr);
  21.510 +        if (addr_len >= 6) { // ""@URI
  21.511 +            const char* endcheck = strstr(raw_addr + 1, "\"@URI");
  21.512 +            if (endcheck && *(endcheck + 5) == '\0') {
  21.513 +                int actual_size = addr_len - 6;
  21.514 +                address = calloc(actual_size + 1, 1);
  21.515 +                if (!address)
  21.516 +                    goto enomem;
  21.517 +                strlcpy(address, raw_addr + 1, actual_size + 1);    
  21.518 +            }
  21.519 +        }
  21.520 +    }
  21.521 +
  21.522 +    pEp_identity *ident = new_identity(address ? address : raw_addr, NULL, NULL, username);
  21.523      if (ident == NULL)
  21.524          goto enomem;
  21.525      free(username);
  21.526 -
  21.527 +    free(address);
  21.528      return ident;
  21.529  
  21.530  enomem:
  21.531 +    free(address);
  21.532      free(username);
  21.533      return NULL;
  21.534  }
  21.535 @@ -2496,10 +2613,30 @@
  21.536      return status;
  21.537  }
  21.538  
  21.539 +static bool _is_marked_as_attachment(struct mailmime_fields *fields)
  21.540 +{
  21.541 +    if (!(fields && fields->fld_list))
  21.542 +        return false;
  21.543 +
  21.544 +    clistiter *cur;
  21.545 +    for (cur = clist_begin(fields->fld_list); cur != NULL ; cur = clist_next(cur)) {
  21.546 +        struct mailmime_field * field = clist_content(cur);
  21.547 +        if (!(field && field->fld_type == MAILMIME_FIELD_DISPOSITION &&
  21.548 +                    field->fld_data.fld_disposition &&
  21.549 +                    field->fld_data.fld_disposition->dsp_type))
  21.550 +            continue;
  21.551 +        if (field->fld_data.fld_disposition->dsp_type->dsp_type ==
  21.552 +                MAILMIME_DISPOSITION_TYPE_ATTACHMENT)
  21.553 +            return true;
  21.554 +    }
  21.555 +
  21.556 +    return false;
  21.557 +}
  21.558 +
  21.559  static PEP_STATUS interpret_MIME(
  21.560          struct mailmime *mime,
  21.561          message *msg,
  21.562 -        bool* raise_msg_attachment
  21.563 +        bool* has_possible_pEp_msg
  21.564      )
  21.565  {
  21.566      PEP_STATUS status = PEP_STATUS_OK;
  21.567 @@ -2507,6 +2644,7 @@
  21.568      assert(mime);
  21.569      assert(msg);
  21.570  
  21.571 +    struct mailmime_fields *fields = mime->mm_mime_fields;
  21.572      struct mailmime_content *content = mime->mm_content_type;
  21.573      if (content) {
  21.574          if (_is_multipart(content, "alternative")) {
  21.575 @@ -2583,21 +2721,22 @@
  21.576                  return PEP_ILLEGAL_VALUE;
  21.577  
  21.578              clistiter *cur;
  21.579 -            // only add raise_msg_attachment on 2nd part!
  21.580 +            // only add has_possible_pEp_msg on 2nd part!
  21.581              int _att_count = 0;
  21.582              for (cur = clist_begin(partlist); cur; cur = clist_next(cur), _att_count++) {
  21.583                  struct mailmime *part= clist_content(cur);
  21.584                  if (part == NULL)
  21.585                      return PEP_ILLEGAL_VALUE;
  21.586 -                status = interpret_MIME(part, msg, _att_count == 1 ? raise_msg_attachment : NULL);
  21.587 +                status = interpret_MIME(part, msg, _att_count == 1 ? has_possible_pEp_msg : NULL);
  21.588                  if (status != PEP_STATUS_OK)
  21.589                      return status;
  21.590              }
  21.591          }
  21.592          else {
  21.593              if (_is_text_part(content, "html") &&
  21.594 -                msg->longmsg_formatted == NULL &&
  21.595 -                msg->longmsg == NULL) {
  21.596 +                    !_is_marked_as_attachment(fields) &&
  21.597 +                    msg->longmsg_formatted == NULL &&
  21.598 +                    msg->longmsg == NULL) {
  21.599                  status = interpret_body(mime, &msg->longmsg_formatted,
  21.600                                          NULL);
  21.601                  if (status)
  21.602 @@ -2609,21 +2748,23 @@
  21.603                      return status;
  21.604              }
  21.605              else if (_is_text_part(content, "plain") && 
  21.606 -                     msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
  21.607 +                    !_is_marked_as_attachment(fields) &&
  21.608 +                    msg->longmsg == NULL && msg->longmsg_formatted == NULL) {
  21.609                  status = interpret_body(mime, &msg->longmsg, NULL);
  21.610                  if (status)
  21.611                      return status;
  21.612              }            
  21.613              else if (_is_text_part(content, NULL) && 
  21.614 -                     !_is_text_part(content, "plain") &&
  21.615 -                     msg->longmsg == NULL) {
  21.616 +                    !_is_marked_as_attachment(fields) &&
  21.617 +                    !_is_text_part(content, "plain") &&
  21.618 +                    msg->longmsg == NULL) {
  21.619                  status = interpret_body(mime, &msg->longmsg, NULL);
  21.620                  if (status)
  21.621                      return status;
  21.622              }
  21.623              else {
  21.624                  // Fixme - we need a control on recursion level here - KG: maybe NOT. We only go to depth 1.
  21.625 -                if (raise_msg_attachment != NULL) {
  21.626 +                if (has_possible_pEp_msg != NULL) {
  21.627                      bool is_msg = (_is_message_part(content, "rfc822") || _is_text_part(content, "rfc822"));
  21.628                      if (is_msg) {
  21.629                          if (content->ct_parameters) {
  21.630 @@ -2633,7 +2774,7 @@
  21.631                                  struct mailmime_parameter * param = clist_content(cur);
  21.632                                  if (param && param->pa_name && strcasecmp(param->pa_name, "forwarded") == 0) {
  21.633                                      if (param->pa_value && strcasecmp(param->pa_value, "no") == 0) {
  21.634 -                                        *raise_msg_attachment = true;
  21.635 +                                        *has_possible_pEp_msg = true;
  21.636                                          break;
  21.637                                      }
  21.638                                  }
  21.639 @@ -2727,18 +2868,8 @@
  21.640  DYNAMIC_API PEP_STATUS mime_decode_message(
  21.641          const char *mimetext,
  21.642          size_t size,
  21.643 -        message **msg
  21.644 -    )
  21.645 -{
  21.646 -    return _mime_decode_message_internal(mimetext, size, msg, NULL);
  21.647 -}        
  21.648 -
  21.649 -
  21.650 -PEP_STATUS _mime_decode_message_internal(
  21.651 -        const char *mimetext,
  21.652 -        size_t size,
  21.653          message **msg,
  21.654 -        bool* raise_msg_attachment
  21.655 +        bool* has_possible_pEp_msg
  21.656      )
  21.657  {
  21.658      PEP_STATUS status = PEP_STATUS_OK;
  21.659 @@ -2782,7 +2913,7 @@
  21.660  
  21.661      if (content) {
  21.662          status = interpret_MIME(mime->mm_data.mm_message.mm_msg_mime,
  21.663 -                _msg, raise_msg_attachment);
  21.664 +                _msg, has_possible_pEp_msg);
  21.665          if (status != PEP_STATUS_OK)
  21.666              goto pEp_error;
  21.667      }
    22.1 --- a/src/etpan_mime.h	Mon Apr 13 13:08:13 2020 +0200
    22.2 +++ b/src/etpan_mime.h	Tue Jul 07 11:53:12 2020 +0200
    22.3 @@ -35,7 +35,6 @@
    22.4          const char * mime_type,
    22.5          char * data,
    22.6          size_t length,
    22.7 -        bool transport_encode,
    22.8          bool set_attachment_forward_comment
    22.9      );
   22.10  
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/src/internal_format.c	Tue Jul 07 11:53:12 2020 +0200
    23.3 @@ -0,0 +1,164 @@
    23.4 +// This file is under GNU General Public License 3.0
    23.5 +// see LICENSE.txt
    23.6 +
    23.7 +#include "platform.h"
    23.8 +
    23.9 +#include "pEp_internal.h"
   23.10 +#include "internal_format.h"
   23.11 +
   23.12 +static struct _internal_message_type {
   23.13 +    char type;
   23.14 +    char subtype;
   23.15 +    const char *mime_type;
   23.16 +} message_type[] = {
   23.17 +    // Keys
   23.18 +    { 'K',  0, "application/keys" },
   23.19 +
   23.20 +    // OpenPGP
   23.21 +    { 'K',  2, "application/pgp-keys" },
   23.22 +
   23.23 +    // x.509
   23.24 +    { 'K',  3, "application/pkcs10" },
   23.25 +    { 'K',  4, "application/pkix-cert" },
   23.26 +    { 'K',  5, "application/pkix-crl" },
   23.27 +    { 'K',  6, "application/pkcs7-mime" },
   23.28 +    { 'K',  7, "application/x-x509-ca-cert" },
   23.29 +    { 'K',  8, "application/x-x509-user-cert" },
   23.30 +    { 'K',  9, "application/x-pkcs7-crl" },
   23.31 +    { 'K', 10, "application/x-pem-file" },
   23.32 +    { 'K', 11, "application/x-pkcs12" },
   23.33 +    { 'K', 12, "application/x-pkcs7-certificates" },
   23.34 +    { 'K', 13, "application/x-pkcs7-certreqresp" },
   23.35 +
   23.36 +    // Sync
   23.37 +    { 'S', 0, "application/pEp.sync" },
   23.38 +
   23.39 +    // Distribution
   23.40 +    { 'D', 0, "application/pEp.distribution" },
   23.41 +    { 'D', 0, "application/pEp.keyreset" },
   23.42 +
   23.43 +    // Authentication
   23.44 +    { 'A', 0, "application/auth" },
   23.45 +    { 'A', 1, "application/signature" },
   23.46 +
   23.47 +    // OpenPGP
   23.48 +    { 'A', 2, "application/pgp-signature" },
   23.49 +
   23.50 +    // x.509
   23.51 +    { 'A', 3, "application/pkcs7-signature" },
   23.52 +    { 'A', 3, "application/x-pkcs7-signature" },
   23.53 +    
   23.54 +    // end marker
   23.55 +    { 0, 0, NULL }
   23.56 +};
   23.57 +
   23.58 +DYNAMIC_API PEP_STATUS encode_internal(
   23.59 +        const char *value,
   23.60 +        size_t size,
   23.61 +        const char *mime_type,
   23.62 +        char **code,
   23.63 +        size_t *code_size
   23.64 +    )
   23.65 +{
   23.66 +    assert(value && size && mime_type && code && code_size);
   23.67 +    if (!(value && size && mime_type && code && code_size))
   23.68 +        return PEP_ILLEGAL_VALUE;
   23.69 +
   23.70 +    *code = NULL;
   23.71 +    *code_size = 0;
   23.72 +
   23.73 +    char type = 0;
   23.74 +    char subtype;
   23.75 +
   23.76 +    struct _internal_message_type *mt;
   23.77 +    for (mt = message_type; mt->type; ++mt) {
   23.78 +        if (strcasecmp(mime_type, mt->mime_type) == 0) {
   23.79 +            type = mt->type;
   23.80 +            subtype = mt->subtype;
   23.81 +            break;
   23.82 +        }
   23.83 +    }
   23.84 +
   23.85 +    // unsupported MIME type
   23.86 +    if (!type)
   23.87 +        return PEP_STATUS_OK;
   23.88 +
   23.89 +    // those are more BSOBs than BLOBS, so we copy
   23.90 +    char *result = malloc(size + 4);
   23.91 +    assert(result);
   23.92 +    if (!result)
   23.93 +        return PEP_OUT_OF_MEMORY;
   23.94 +
   23.95 +    result[0] = 0;
   23.96 +    result[1] = type;
   23.97 +    result[2] = subtype;
   23.98 +    result[3] = 0;
   23.99 +
  23.100 +    memcpy(result + 4, value, size);
  23.101 +    
  23.102 +    *code = result;
  23.103 +    *code_size = size + 4;
  23.104 +
  23.105 +    return PEP_STATUS_OK;
  23.106 +}
  23.107 +
  23.108 +DYNAMIC_API PEP_STATUS decode_internal(
  23.109 +        const char *code,
  23.110 +        size_t code_size,
  23.111 +        char **value,
  23.112 +        size_t *size,
  23.113 +        char **mime_type
  23.114 +    )
  23.115 +{
  23.116 +    assert(value && size && mime_type && code && !code[0] && code_size);
  23.117 +    if (!(value && size && mime_type && code && !code[0] && code_size))
  23.118 +        return PEP_ILLEGAL_VALUE;
  23.119 +
  23.120 +    *value = NULL;
  23.121 +    *size = 0;
  23.122 +    *mime_type = NULL;
  23.123 +
  23.124 +    // elevated attachments have at least 5 bytes
  23.125 +    assert(code_size > 4);
  23.126 +    if (code_size < 5)
  23.127 +        return PEP_ILLEGAL_VALUE;
  23.128 +
  23.129 +    assert(!code[0]);
  23.130 +    char type = code[1];
  23.131 +    char subtype = code[2];
  23.132 +    // char reserved = code[3];
  23.133 +
  23.134 +    char *_mime_type = NULL;
  23.135 +
  23.136 +    struct _internal_message_type *mt;
  23.137 +    for (mt = message_type; mt->type; ++mt) {
  23.138 +        if (type == mt->type && subtype == mt->subtype) {
  23.139 +            assert(mt->mime_type);
  23.140 +            _mime_type = strdup(mt->mime_type);
  23.141 +            assert(_mime_type);
  23.142 +            if (!_mime_type)
  23.143 +                return PEP_OUT_OF_MEMORY;
  23.144 +
  23.145 +            break;
  23.146 +        }
  23.147 +    }
  23.148 +
  23.149 +    if (!_mime_type)
  23.150 +        return PEP_ILLEGAL_VALUE;
  23.151 +
  23.152 +    char *result = malloc(code_size - 4);
  23.153 +    assert(result);
  23.154 +    if (!result) {
  23.155 +        free(_mime_type);
  23.156 +        return PEP_OUT_OF_MEMORY;
  23.157 +    }
  23.158 +
  23.159 +    memcpy(result, code + 4, code_size - 4);
  23.160 +
  23.161 +    *value = result;
  23.162 +    *size = code_size - 4;
  23.163 +    *mime_type = _mime_type;
  23.164 +
  23.165 +    return PEP_STATUS_OK;
  23.166 +}
  23.167 +
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/src/internal_format.h	Tue Jul 07 11:53:12 2020 +0200
    24.3 @@ -0,0 +1,72 @@
    24.4 +// This file is under GNU General Public License 3.0
    24.5 +// see LICENSE.txt
    24.6 +
    24.7 +#pragma once
    24.8 +
    24.9 +#include "message.h"
   24.10 +#include "cryptotech.h"
   24.11 +
   24.12 +#ifdef __cplusplus
   24.13 +extern "C" {
   24.14 +#endif
   24.15 +
   24.16 +// encode_internal() - encode to the internal message format
   24.17 +//
   24.18 +//  parameters:
   24.19 +//      value (in)          blob
   24.20 +//      size (in)           size of value
   24.21 +//      mime_type (in)      string of MIME type
   24.22 +//      code (out)          blob in Internal Message Format
   24.23 +//      code_size (out)     size of code
   24.24 +//
   24.25 +//  caveat:
   24.26 +//      call this for the data in an attachment
   24.27 +//
   24.28 +//      for unsupported MIME types this function is returning NULL for code and
   24.29 +//      does not fail
   24.30 +//
   24.31 +//      for supported MIME types this function is creating the internal message
   24.32 +//      format by copying the data in value
   24.33 +//
   24.34 +//      code goes into the ownership of the caller
   24.35 +//
   24.36 +//  see also:
   24.37 +//      https://dev.pep.foundation/Engine/ElevatedAttachments
   24.38 +
   24.39 +DYNAMIC_API PEP_STATUS encode_internal(
   24.40 +        const char *value,
   24.41 +        size_t size,
   24.42 +        const char *mime_type,
   24.43 +        char **code,
   24.44 +        size_t *code_size
   24.45 +    );
   24.46 +
   24.47 +
   24.48 +// decode_internal() - decode from internal message format
   24.49 +//
   24.50 +//  parameters:
   24.51 +//      code (in)           blob in Internal Message Format
   24.52 +//      code_size (in)      size of code
   24.53 +//      tech (in)           crypto tech for MIME type, PEP_crypt_none for auto
   24.54 +//      value (out)         blob or string for longmsg
   24.55 +//      size (out)          size of value
   24.56 +//      mime_type (out)     string with MIME type or NULL for longmsg
   24.57 +//
   24.58 +//  caveat:
   24.59 +//      this functions copies data from the code
   24.60 +//
   24.61 +//      value goes into the ownership of the caller
   24.62 +//      mime_type goes into the ownership of the caller
   24.63 +
   24.64 +DYNAMIC_API PEP_STATUS decode_internal(
   24.65 +        const char *code,
   24.66 +        size_t code_size,
   24.67 +        char **value,
   24.68 +        size_t *size,
   24.69 +        char **mime_type
   24.70 +    );
   24.71 +
   24.72 +
   24.73 +#ifdef __cplusplus
   24.74 +}
   24.75 +#endif
    25.1 --- a/src/key_reset.c	Mon Apr 13 13:08:13 2020 +0200
    25.2 +++ b/src/key_reset.c	Tue Jul 07 11:53:12 2020 +0200
    25.3 @@ -728,7 +728,7 @@
    25.4      message* output_msg = NULL;
    25.5      
    25.6      status = encrypt_message(session, reset_msg, NULL,
    25.7 -                             &output_msg, PEP_enc_PGP_MIME,
    25.8 +                             &output_msg, PEP_enc_auto,
    25.9                               PEP_encrypt_flag_key_reset_only);
   25.10  
   25.11      if (status == PEP_STATUS_OK)
   25.12 @@ -782,6 +782,16 @@
   25.13          if (is_me(session, curr_id))
   25.14              continue;
   25.15              
   25.16 +        // Also, don't bother to send it to non-pEp-users 
   25.17 +        bool pEp_user = false;
   25.18 +        status = is_pEp_user(session, curr_id, &pEp_user);
   25.19 +
   25.20 +        if (status != PEP_STATUS_OK)
   25.21 +            goto pEp_free;
   25.22 +
   25.23 +        if (!pEp_user)
   25.24 +            continue;
   25.25 +            
   25.26          // Check if they've already been told - this shouldn't be the case, but...
   25.27          bool contacted = false;
   25.28          status = has_key_reset_been_sent(session, from_ident->address, user_id, old_fpr, &contacted);
   25.29 @@ -964,7 +974,7 @@
   25.30          
   25.31          // encrypt this baby and get out
   25.32          // extra keys???
   25.33 -        status = encrypt_message(session, outmsg, NULL, &enc_msg, PEP_enc_PGP_MIME, PEP_encrypt_flag_key_reset_only);
   25.34 +        status = encrypt_message(session, outmsg, NULL, &enc_msg, PEP_enc_auto, PEP_encrypt_flag_key_reset_only);
   25.35          
   25.36          if (status != PEP_STATUS_OK) {
   25.37              goto pEp_free;
    26.1 --- a/src/keymanagement.c	Mon Apr 13 13:08:13 2020 +0200
    26.2 +++ b/src/keymanagement.c	Tue Jul 07 11:53:12 2020 +0200
    26.3 @@ -574,6 +574,7 @@
    26.4      }
    26.5      
    26.6      transfer_ident_lang_and_flags(return_id, stored_ident);
    26.7 +    return_id->enc_format = stored_ident->enc_format;    
    26.8          
    26.9      if (return_id->comm_type == PEP_ct_unknown)
   26.10          return_id->comm_type = PEP_ct_key_not_found;
   26.11 @@ -1061,12 +1062,20 @@
   26.12      assert(session);
   26.13      assert(identity);
   26.14      assert(!EMPTYSTR(identity->address));
   26.15 -    assert(!EMPTYSTR(identity->user_id));
   26.16  
   26.17 -    if (!session || !identity || EMPTYSTR(identity->address) ||
   26.18 -        EMPTYSTR(identity->user_id))
   26.19 +    if (!session || EMPTYSTR(identity->address))
   26.20          return PEP_ILLEGAL_VALUE;
   26.21  
   26.22 +    // this is leading to crashes otherwise
   26.23 +
   26.24 +    if (!(identity->user_id && identity->user_id[0])) {
   26.25 +        free(identity->user_id);
   26.26 +        identity->user_id = strdup(PEP_OWN_USERID);
   26.27 +        assert(identity->user_id);
   26.28 +        if (!identity->user_id)
   26.29 +            return PEP_OUT_OF_MEMORY;
   26.30 +    }
   26.31 +
   26.32      pEp_identity *stored_identity = NULL;
   26.33      char* revoked_fpr = NULL; 
   26.34      bool valid_key_found = false;
   26.35 @@ -2022,3 +2031,97 @@
   26.36      sqlite3_reset(session->is_mistrusted_key);
   26.37      return status;
   26.38  }
   26.39 +
   26.40 +static PEP_STATUS _wipe_default_key_if_invalid(PEP_SESSION session,
   26.41 +                                         pEp_identity* ident) {
   26.42 +    
   26.43 +    PEP_STATUS status = PEP_STATUS_OK;
   26.44 +    
   26.45 +    if (!ident->user_id)
   26.46 +        return PEP_ILLEGAL_VALUE;
   26.47 +        
   26.48 +    if (!ident->fpr)
   26.49 +        return status;
   26.50 +    
   26.51 +    char* cached_fpr = strdup(ident->fpr);
   26.52 +    if (!ident->fpr)
   26.53 +        return PEP_OUT_OF_MEMORY;
   26.54 +        
   26.55 +    PEP_STATUS keystatus = validate_fpr(session, ident, true, false);
   26.56 +    switch (keystatus) {
   26.57 +        case PEP_STATUS_OK:
   26.58 +            // Check for non-renewable expiry and 
   26.59 +            // if so, fallthrough
   26.60 +            if (ident->comm_type != PEP_ct_key_expired_but_confirmed &&
   26.61 +                    ident->comm_type != PEP_ct_key_expired) {
   26.62 +                break;
   26.63 +            }        
   26.64 +        case PEP_KEY_UNSUITABLE:
   26.65 +        case PEP_KEY_BLACKLISTED:
   26.66 +            // Remove key as default for all identities and users 
   26.67 +            status = remove_fpr_as_default(session, cached_fpr);
   26.68 +            break;   
   26.69 +        default:
   26.70 +            break;
   26.71 +    }     
   26.72 +    free(cached_fpr);
   26.73 +    
   26.74 +    if (status == PEP_STATUS_OK)
   26.75 +        status = myself(session, ident);
   26.76 +            
   26.77 +    return status;                                        
   26.78 +}
   26.79 +
   26.80 +PEP_STATUS clean_own_key_defaults(PEP_SESSION session) {
   26.81 +    identity_list* idents = NULL;
   26.82 +    PEP_STATUS status = own_identities_retrieve(session, &idents);
   26.83 +    if (status != PEP_STATUS_OK)
   26.84 +        return status;
   26.85 +        
   26.86 +    if (!idents)
   26.87 +        return PEP_STATUS_OK;
   26.88 +
   26.89 +    if (!idents->ident && !idents->next) {
   26.90 +        free_identity_list(idents);
   26.91 +        return PEP_STATUS_OK;
   26.92 +    } // Kludge: FIX own_identities_retrieve. Should return NULL, not empty list    
   26.93 +        
   26.94 +    identity_list* curr = idents;
   26.95 +    
   26.96 +    for ( ; curr ; curr = curr->next) {
   26.97 +        pEp_identity* ident = curr->ident;
   26.98 +        if (!ident)
   26.99 +            continue;
  26.100 +        
  26.101 +        _wipe_default_key_if_invalid(session, ident);    
  26.102 +    }   
  26.103 +    
  26.104 +    free_identity_list(idents);
  26.105 +    
  26.106 +    // Also remove invalid default user key
  26.107 +    char* own_id = NULL;
  26.108 +
  26.109 +    status = get_default_own_userid(session, &own_id);
  26.110 +
  26.111 +    if (status != PEP_STATUS_OK)
  26.112 +        return status;
  26.113 +
  26.114 +    if (own_id) {
  26.115 +        char* user_default_key = NULL;
  26.116 +        status = get_user_default_key(session, own_id, &user_default_key);
  26.117 +        if (status != PEP_STATUS_OK) {
  26.118 +            free(own_id);
  26.119 +            if (status == PEP_KEY_NOT_FOUND)
  26.120 +                status = PEP_STATUS_OK;
  26.121 +            else
  26.122 +                return status;
  26.123 +        }
  26.124 +        else if (user_default_key) {
  26.125 +            pEp_identity* empty_user = new_identity(NULL, user_default_key, NULL, own_id);
  26.126 +            _wipe_default_key_if_invalid(session, empty_user);       
  26.127 +            free(user_default_key);
  26.128 +        }
  26.129 +        free(own_id);    
  26.130 +    }
  26.131 +    return status;
  26.132 +}
    27.1 --- a/src/keymanagement.h	Mon Apr 13 13:08:13 2020 +0200
    27.2 +++ b/src/keymanagement.h	Tue Jul 07 11:53:12 2020 +0200
    27.3 @@ -408,6 +408,8 @@
    27.4                              bool* is_address_default,
    27.5                              bool check_blacklist);
    27.6  
    27.7 +PEP_STATUS clean_own_key_defaults(PEP_SESSION session);
    27.8 +
    27.9  #ifdef __cplusplus
   27.10  }
   27.11  #endif
    28.1 --- a/src/message.h	Mon Apr 13 13:08:13 2020 +0200
    28.2 +++ b/src/message.h	Tue Jul 07 11:53:12 2020 +0200
    28.3 @@ -28,16 +28,6 @@
    28.4      PEP_dir_outgoing
    28.5  } PEP_msg_direction;
    28.6  
    28.7 -typedef enum _PEP_enc_format {
    28.8 -    PEP_enc_none = 0,                       // message is not encrypted
    28.9 -    PEP_enc_pieces = 1,                     // inline PGP + PGP extensions, was removed
   28.10 -    PEP_enc_inline = 1,                     // still there
   28.11 -    PEP_enc_S_MIME,                         // RFC5751
   28.12 -    PEP_enc_PGP_MIME,                       // RFC3156
   28.13 -    PEP_enc_PEP,                            // pEp encryption format
   28.14 -    PEP_enc_PGP_MIME_Outlook1               // Message B0rken by Outlook type 1
   28.15 -} PEP_enc_format;
   28.16 -
   28.17  struct _message_ref_list;
   28.18  
   28.19  typedef struct _message {
    29.1 --- a/src/message_api.c	Mon Apr 13 13:08:13 2020 +0200
    29.2 +++ b/src/message_api.c	Tue Jul 07 11:53:12 2020 +0200
    29.3 @@ -3,6 +3,7 @@
    29.4  
    29.5  #include "pEp_internal.h"
    29.6  #include "message_api.h"
    29.7 +#include "pEpEngine.h"
    29.8  
    29.9  #include "platform.h"
   29.10  #include "mime.h"
   29.11 @@ -11,10 +12,12 @@
   29.12  #include "KeySync_fsm.h"
   29.13  #include "base64.h"
   29.14  #include "resource_id.h"
   29.15 +#include "internal_format.h"
   29.16  
   29.17  #include <assert.h>
   29.18  #include <string.h>
   29.19  #include <stdlib.h>
   29.20 +#include <stdint.h>
   29.21  #include <math.h>
   29.22  
   29.23  
   29.24 @@ -70,8 +73,6 @@
   29.25          return "have_no_key";
   29.26      case PEP_rating_unencrypted:
   29.27          return "unencrypted";
   29.28 -    case PEP_rating_unencrypted_for_some: // don't use this any more
   29.29 -        return "undefined";
   29.30      case PEP_rating_unreliable:
   29.31          return "unreliable";
   29.32      case PEP_rating_reliable:
   29.33 @@ -298,8 +299,18 @@
   29.34      assert(shortmsg);
   29.35      
   29.36      unsigned char pEpstr[] = PEP_SUBJ_STRING;
   29.37 -    assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) != 0); 
   29.38 +
   29.39 +    // assert(strcmp(shortmsg, "pEp") != 0 && _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) != 0); 
   29.40 +    // in case encrypt_message() is called twice with a different passphrase this was done already
   29.41      
   29.42 +    if (strcmp(shortmsg, "pEp") == 0 || _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
   29.43 +        char *ptext = strdup(longmsg);
   29.44 +        assert(ptext);
   29.45 +        if (!ptext)
   29.46 +            return NULL;
   29.47 +        return ptext;
   29.48 +    }
   29.49 +
   29.50      if (!shortmsg || strcmp(shortmsg, "pEp") == 0 || 
   29.51                       _unsigned_signed_strcmp(pEpstr, shortmsg, PEP_SUBJ_BYTELEN) == 0) {
   29.52          if (!longmsg) {
   29.53 @@ -923,7 +934,7 @@
   29.54                );
   29.55              
   29.56      /* Turn message into a MIME-blob */
   29.57 -    status = _mime_encode_message_internal(attachment, false, &message_text, true, false);
   29.58 +    status = mime_encode_message(attachment, false, &message_text, false);
   29.59          
   29.60      if (status != PEP_STATUS_OK)
   29.61          goto enomem;
   29.62 @@ -961,7 +972,7 @@
   29.63      if (status)
   29.64          return status;
   29.65  
   29.66 -    dst->enc_format = PEP_enc_inline;
   29.67 +    dst->enc_format = src->enc_format;
   29.68  
   29.69      // shortmsg is being copied
   29.70      if (src->shortmsg) {
   29.71 @@ -987,13 +998,81 @@
   29.72  
   29.73      dst->longmsg = _ctext;
   29.74  
   29.75 -    // longmsg_formatted is unsupported
   29.76 -
   29.77 -    // attachments are going unencrypted
   29.78 -    bloblist_t *bl = bloblist_dup(src->attachments);
   29.79 -    if (!bl)
   29.80 +    dst->attachments = new_bloblist(NULL, 0, NULL, NULL);
   29.81 +    if (!dst->attachments)
   29.82          return PEP_OUT_OF_MEMORY;
   29.83 -    dst->attachments = bl;
   29.84 +
   29.85 +    bloblist_t *ad = dst->attachments;
   29.86 +
   29.87 +    if (!EMPTYSTR(src->longmsg_formatted)) {
   29.88 +        status = encrypt_and_sign(session, keys, src->longmsg_formatted,
   29.89 +                strlen(src->longmsg_formatted), &ctext, &csize);
   29.90 +        if (status)
   29.91 +            return status;
   29.92 +
   29.93 +        char *_ctext = realloc(ctext, csize + 1);
   29.94 +        assert(_ctext);
   29.95 +        if (!_ctext)
   29.96 +            return PEP_OUT_OF_MEMORY;
   29.97 +        _ctext[csize] = 0;
   29.98 +
   29.99 +        ad = bloblist_add(ad, _ctext, csize + 1, "text/html", NULL);
  29.100 +        if (!ad)
  29.101 +            return PEP_OUT_OF_MEMORY;
  29.102 +
  29.103 +        ad->disposition = PEP_CONTENT_DISP_INLINE;
  29.104 +    }
  29.105 +
  29.106 +    if (src->attachments && src->attachments->value) {
  29.107 +        bloblist_t *as;
  29.108 +        for (as = src->attachments; as && as->value; as = as->next) {
  29.109 +            char *value = NULL;
  29.110 +            size_t size = 0;
  29.111 +            if (src->enc_format == PEP_enc_inline_EA) {
  29.112 +                status = encode_internal(as->value, as->size, as->mime_type,
  29.113 +                        &value, &size);
  29.114 +                if (status)
  29.115 +                    return status;
  29.116 +                if (!value) {
  29.117 +                    value = as->value;
  29.118 +                    size = as->size;
  29.119 +                }
  29.120 +            }
  29.121 +            else {
  29.122 +                value = as->value;
  29.123 +                size = as->size;
  29.124 +            }
  29.125 +            status = encrypt_and_sign(session, keys, value, size, &ctext,
  29.126 +                    &csize);
  29.127 +            if (value != as->value)
  29.128 +                free(value);
  29.129 +            if (status)
  29.130 +                return status;
  29.131 +
  29.132 +            char *_ctext = realloc(ctext, csize + 1);
  29.133 +            assert(_ctext);
  29.134 +            if (!_ctext)
  29.135 +                return PEP_OUT_OF_MEMORY;
  29.136 +            _ctext[csize] = 0;
  29.137 +
  29.138 +            size_t len = strlen(as->filename);
  29.139 +            char *filename = malloc(len + 5);
  29.140 +            assert(filename);
  29.141 +            if (!filename)
  29.142 +                return PEP_OUT_OF_MEMORY;
  29.143 +
  29.144 +            memcpy(filename, as->filename, len);
  29.145 +            memcpy(filename + len, ".pgp", 5);
  29.146 +
  29.147 +            ad = bloblist_add(ad, _ctext, csize + 1, "application/octet-stream", filename);
  29.148 +            free(filename);
  29.149 +            filename = NULL;
  29.150 +            if (!ad)
  29.151 +                return PEP_OUT_OF_MEMORY;
  29.152 +
  29.153 +            ad->disposition = as->disposition;
  29.154 +        }
  29.155 +    }
  29.156  
  29.157      return PEP_STATUS_OK;
  29.158  }
  29.159 @@ -1029,10 +1108,8 @@
  29.160      _src->attachments = src->attachments;
  29.161      _src->enc_format = PEP_enc_none;
  29.162      
  29.163 -    // These vars are here to be clear, and because I don't know how this may change in the near future.
  29.164      bool wrapped = (wrap_type != PEP_message_unwrapped);
  29.165 -    bool mime_encode = !wrapped;
  29.166 -    status = _mime_encode_message_internal(_src, true, &mimetext, mime_encode, wrapped);
  29.167 +    status = mime_encode_message(_src, true, &mimetext, wrapped);
  29.168      assert(status == PEP_STATUS_OK);
  29.169      if (status != PEP_STATUS_OK)
  29.170          goto pEp_error;
  29.171 @@ -1054,7 +1131,7 @@
  29.172          status = encrypt_and_sign(session, keys, mimetext, strlen(mimetext),
  29.173              &ctext, &csize);
  29.174      free(mimetext);
  29.175 -    if (ctext == NULL)
  29.176 +    if (ctext == NULL || status)
  29.177          goto pEp_error;
  29.178  
  29.179      dst->longmsg = strdup("this message was encrypted with p≡p "
  29.180 @@ -1316,11 +1393,12 @@
  29.181      if (max_comm_type == PEP_ct_mistrusted)
  29.182          return PEP_ct_mistrusted;
  29.183  
  29.184 -    if (!is_me(session, ident))
  29.185 +    if (!is_me(session, ident)) {
  29.186          status = update_identity(session, ident);
  29.187 -    else
  29.188 -        // ???
  29.189 +    }
  29.190 +    else {
  29.191          status = _myself(session, ident, false, false, true);
  29.192 +    }
  29.193  
  29.194      if (status == PEP_STATUS_OK) {
  29.195          if (ident->comm_type == PEP_ct_compromised)
  29.196 @@ -1449,7 +1527,9 @@
  29.197  bool import_attached_keys(
  29.198          PEP_SESSION session,
  29.199          message *msg,
  29.200 -        identity_list **private_idents
  29.201 +        identity_list **private_idents, 
  29.202 +        stringlist_t** imported_key_list,
  29.203 +        uint64_t* changed_keys
  29.204      )
  29.205  {
  29.206      assert(session);
  29.207 @@ -1510,7 +1590,11 @@
  29.208                  }
  29.209              }
  29.210              identity_list *local_private_idents = NULL;
  29.211 -            PEP_STATUS import_status = import_key(session, blob_value, blob_size, &local_private_idents);
  29.212 +            PEP_STATUS import_status = _import_key_with_fpr_return(
  29.213 +                                                  session, blob_value, blob_size, 
  29.214 +                                                  &local_private_idents,
  29.215 +                                                  imported_key_list,
  29.216 +                                                  changed_keys);
  29.217              bloblist_t* to_delete = NULL;
  29.218              switch (import_status) {
  29.219                  case PEP_NO_KEY_IMPORTED:
  29.220 @@ -1615,7 +1699,8 @@
  29.221      assert(msg);
  29.222  
  29.223      if (is_PGP_message_text(msg->longmsg)) {
  29.224 -        msg->enc_format = PEP_enc_inline;
  29.225 +        if (msg->enc_format != PEP_enc_inline_EA)
  29.226 +            msg->enc_format = PEP_enc_inline;
  29.227          return PEP_crypt_OpenPGP;
  29.228      }
  29.229      else if (msg->attachments && msg->attachments->next &&
  29.230 @@ -1669,6 +1754,60 @@
  29.231      }                   
  29.232  }
  29.233  
  29.234 +static PEP_STATUS id_list_set_enc_format(PEP_SESSION session, identity_list* id_list, PEP_enc_format enc_format) {
  29.235 +    PEP_STATUS status = PEP_STATUS_OK;
  29.236 +    identity_list* id_list_curr = id_list;
  29.237 +    for ( ; id_list_curr && id_list_curr->ident && status == PEP_STATUS_OK; id_list_curr = id_list_curr->next) {
  29.238 +        status = set_ident_enc_format(session, id_list_curr->ident, enc_format);
  29.239 +    }
  29.240 +    return status;
  29.241 +}
  29.242 +
  29.243 +// N.B.
  29.244 +// depends on update_identity and friends having already been called on list
  29.245 +static void update_encryption_format(identity_list* id_list, PEP_enc_format* enc_format) {
  29.246 +    identity_list* id_list_curr;
  29.247 +    for (id_list_curr = id_list; id_list_curr && id_list_curr->ident; id_list_curr = id_list_curr->next) {
  29.248 +        PEP_enc_format format = id_list_curr->ident->enc_format;
  29.249 +        if (format != PEP_enc_none) {
  29.250 +            *enc_format = format;
  29.251 +            break;
  29.252 +        }
  29.253 +    }
  29.254 +}
  29.255 +
  29.256 +PEP_STATUS probe_encrypt(PEP_SESSION session, const char *fpr)
  29.257 +{
  29.258 +    assert(session);
  29.259 +    if (!session)
  29.260 +        return PEP_ILLEGAL_VALUE;
  29.261 +
  29.262 +    if (EMPTYSTR(fpr))
  29.263 +        return PEP_KEY_NOT_FOUND;
  29.264 +
  29.265 +    stringlist_t *keylist = new_stringlist(fpr);
  29.266 +    if (!keylist)
  29.267 +        return PEP_OUT_OF_MEMORY;
  29.268 +
  29.269 +    char *ctext = NULL;
  29.270 +    size_t csize = 0;
  29.271 +    PEP_STATUS status = encrypt_and_sign(session, keylist, "pEp", 4, &ctext, &csize);
  29.272 +    free(ctext);
  29.273 +
  29.274 +    return status;
  29.275 +}
  29.276 +
  29.277 +static bool failed_test(PEP_STATUS status)
  29.278 +{
  29.279 +    if (status == PEP_OUT_OF_MEMORY ||
  29.280 +            status == PEP_PASSPHRASE_REQUIRED ||
  29.281 +            status == PEP_WRONG_PASSPHRASE  ||
  29.282 +            status == PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED)
  29.283 +        return true;
  29.284 +
  29.285 +    return false;
  29.286 +}
  29.287 +
  29.288  DYNAMIC_API PEP_STATUS encrypt_message(
  29.289          PEP_SESSION session,
  29.290          message *src,
  29.291 @@ -1717,6 +1856,11 @@
  29.292      if (status != PEP_STATUS_OK)
  29.293          goto pEp_error;
  29.294  
  29.295 +    // is a passphrase needed?
  29.296 +    status = probe_encrypt(session, src->from->fpr);
  29.297 +    if (failed_test(status))
  29.298 +        return status;
  29.299 +
  29.300      char* send_fpr = strdup(src->from->fpr ? src->from->fpr : "");
  29.301      src->_sender_fpr = send_fpr;
  29.302      
  29.303 @@ -1929,6 +2073,23 @@
  29.304      
  29.305      if (max_version_major == 1)
  29.306          force_v_1 = true;
  29.307 +
  29.308 +    if (enc_format == PEP_enc_auto) {
  29.309 +        update_encryption_format(src->to, &enc_format);
  29.310 +        if (enc_format == PEP_enc_auto && src->cc)
  29.311 +            update_encryption_format(src->cc, &enc_format);
  29.312 +        if (enc_format == PEP_enc_auto && src->bcc)
  29.313 +            update_encryption_format(src->bcc, &enc_format);
  29.314 +        if (enc_format == PEP_enc_auto)
  29.315 +            enc_format = PEP_enc_PEP;
  29.316 +    }    
  29.317 +    else if (enc_format != PEP_enc_none) {
  29.318 +        status = id_list_set_enc_format(session, src->to, enc_format);
  29.319 +        status = ((status != PEP_STATUS_OK || !(src->cc)) ? status : id_list_set_enc_format(session, src->cc, enc_format));
  29.320 +        status = ((status != PEP_STATUS_OK || !(src->bcc)) ? status : id_list_set_enc_format(session, src->bcc, enc_format));
  29.321 +        if (status != PEP_STATUS_OK)
  29.322 +            goto pEp_error;
  29.323 +    }
  29.324          
  29.325      if (enc_format == PEP_enc_none || !dest_keys_found ||
  29.326          stringlist_length(keys)  == 0 ||
  29.327 @@ -1950,7 +2111,7 @@
  29.328              
  29.329          // FIXME - we need to deal with transport types (via flag)
  29.330          message_wrap_type wrap_type = PEP_message_unwrapped;
  29.331 -        if ((enc_format != PEP_enc_inline) && (!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  29.332 +        if ((enc_format != PEP_enc_inline) && (enc_format != PEP_enc_inline_EA) && (!force_v_1) && ((max_comm_type | PEP_ct_confirmed) == PEP_ct_pEp)) {
  29.333              wrap_type = ((flags & PEP_encrypt_flag_key_reset_only) ? PEP_message_key_reset : PEP_message_default);
  29.334              _src = wrap_message_as_attachment(NULL, src, wrap_type, false, extra, max_version_major, max_version_minor);
  29.335              if (!_src)
  29.336 @@ -1958,7 +2119,7 @@
  29.337          }
  29.338          else {
  29.339              // hide subject
  29.340 -            if (enc_format != PEP_enc_inline) {
  29.341 +            if (enc_format != PEP_enc_inline && enc_format != PEP_enc_inline_EA) {
  29.342                  status = replace_subject(_src);
  29.343                  if (status == PEP_OUT_OF_MEMORY)
  29.344                      goto enomem;
  29.345 @@ -1980,6 +2141,8 @@
  29.346                  break;
  29.347  
  29.348              case PEP_enc_inline:
  29.349 +            case PEP_enc_inline_EA:
  29.350 +                _src->enc_format = enc_format;
  29.351                  status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  29.352                  break;
  29.353  
  29.354 @@ -2107,6 +2270,11 @@
  29.355      if (status != PEP_STATUS_OK)
  29.356          goto pEp_free;
  29.357  
  29.358 +    // is a passphrase needed?
  29.359 +    status = probe_encrypt(session, own_identity->fpr);
  29.360 +    if (failed_test(status))
  29.361 +        goto pEp_free;
  29.362 +
  29.363      // Ok, now we know the address is an own address. All good. Then...
  29.364      own_private_fpr = own_identity->fpr;
  29.365      own_identity->fpr = strdup(to_fpr);
  29.366 @@ -2162,6 +2330,10 @@
  29.367          status = PEP_UNKNOWN_ERROR;
  29.368          goto pEp_free;
  29.369      }
  29.370 +    else if (status) {
  29.371 +        free(encrypted_key_text);
  29.372 +        goto pEp_free; // FIXME - we need an error return overall
  29.373 +    }
  29.374  
  29.375      // We will have to delete this before returning, as we allocated it.
  29.376      bloblist_t* created_bl = NULL;
  29.377 @@ -2285,6 +2457,11 @@
  29.378      if (!target_fpr)
  29.379          return PEP_KEY_NOT_FOUND; // FIXME: Error condition
  29.380   
  29.381 +    // is a passphrase needed?
  29.382 +    status = probe_encrypt(session, target_fpr);
  29.383 +    if (failed_test(status))
  29.384 +        return status;
  29.385 +
  29.386      keys = new_stringlist(target_fpr);
  29.387      
  29.388      stringlist_t *_k = keys;
  29.389 @@ -2318,6 +2495,8 @@
  29.390              break;
  29.391  
  29.392          case PEP_enc_inline:
  29.393 +        case PEP_enc_inline_EA:
  29.394 +            _src->enc_format = enc_format;
  29.395              status = encrypt_PGP_inline(session, _src, keys, msg, flags);
  29.396              break;
  29.397  
  29.398 @@ -2669,6 +2848,7 @@
  29.399      switch (src->enc_format) {
  29.400          case PEP_enc_PGP_MIME:
  29.401          case PEP_enc_inline:
  29.402 +        case PEP_enc_inline_EA:
  29.403          case PEP_enc_PGP_MIME_Outlook1:
  29.404  //        case PEP_enc_none: // FIXME - this is wrong
  29.405  
  29.406 @@ -2779,6 +2959,7 @@
  29.407          break;
  29.408  
  29.409          case PEP_enc_inline:
  29.410 +        case PEP_enc_inline_EA:
  29.411              *crypto_text = src->longmsg;
  29.412              *text_size = strlen(*crypto_text);
  29.413              break;
  29.414 @@ -2926,8 +3107,13 @@
  29.415                          if (!has_uri_prefix)
  29.416                              filename_uri = build_uri("file", pgp_filename);
  29.417  
  29.418 -                        _m = bloblist_add(_m, ptext, psize, mime_type,
  29.419 -                             (filename_uri ? filename_uri : pgp_filename));
  29.420 +                        char *_filename = filename_uri ? filename_uri : pgp_filename;
  29.421 +                        if (strcasecmp(_filename, "file://distribution.pEp") == 0)
  29.422 +                            _m = bloblist_add(_m, ptext, psize, "application/pEp.distribution", _filename);
  29.423 +                        else if (strcasecmp(_filename, "file://sync.pEp") == 0)
  29.424 +                            _m = bloblist_add(_m, ptext, psize, "application/pEp.sync", _filename);
  29.425 +                        else
  29.426 +                            _m = bloblist_add(_m, ptext, psize, mime_type, _filename);
  29.427  
  29.428                          free(pgp_filename);
  29.429                          free(filename_uri);
  29.430 @@ -2943,8 +3129,14 @@
  29.431                          if (!has_uri_prefix)
  29.432                              filename_uri = build_uri("file", filename);
  29.433  
  29.434 -                        _m = bloblist_add(_m, ptext, psize, mime_type,
  29.435 -                             (filename_uri ? filename_uri : filename));
  29.436 +                        char *_filename = filename_uri ? filename_uri : filename;
  29.437 +                        if (strcasecmp(_filename, "file://distribution.pEp") == 0)
  29.438 +                            _m = bloblist_add(_m, ptext, psize, "application/pEp.distribution", _filename);
  29.439 +                        else if (strcasecmp(_filename, "file://sync.pEp") == 0)
  29.440 +                            _m = bloblist_add(_m, ptext, psize, "application/pEp.sync", _filename);
  29.441 +                        else
  29.442 +                            _m = bloblist_add(_m, ptext, psize, mime_type, _filename);
  29.443 +
  29.444                          free(filename);
  29.445                          free(filename_uri);
  29.446                          if (_m == NULL)
  29.447 @@ -2993,18 +3185,21 @@
  29.448      return status;
  29.449  }
  29.450  
  29.451 -static PEP_STATUS import_priv_keys_from_decrypted_msg(PEP_SESSION session,
  29.452 +// This is misleading - this imports ALL the keys!
  29.453 +static PEP_STATUS import_keys_from_decrypted_msg(PEP_SESSION session,
  29.454                                                        message* msg,
  29.455 -                                                      bool* imported_keys,
  29.456 +                                                      bool* keys_were_imported,
  29.457                                                        bool* imported_private,
  29.458 -                                                      identity_list** private_il)
  29.459 +                                                      identity_list** private_il,
  29.460 +                                                      stringlist_t** keylist,
  29.461 +                                                      uint64_t* changed_keys)
  29.462  {
  29.463 -    assert(msg && imported_keys && imported_private);
  29.464 -    if (!(msg && imported_keys && imported_private))
  29.465 +    assert(msg && keys_were_imported && imported_private);
  29.466 +    if (!(msg && keys_were_imported && imported_private))
  29.467          return PEP_ILLEGAL_VALUE;
  29.468  
  29.469      PEP_STATUS status = PEP_STATUS_OK;
  29.470 -    *imported_keys = false;
  29.471 +    *keys_were_imported = false;
  29.472      *imported_private = false;
  29.473      if (private_il)
  29.474          *private_il = NULL;
  29.475 @@ -3012,7 +3207,7 @@
  29.476      // check for private key in decrypted message attachment while importing
  29.477      identity_list *_private_il = NULL;
  29.478  
  29.479 -    bool _imported_keys = import_attached_keys(session, msg, &_private_il);
  29.480 +    bool _keys_were_imported = import_attached_keys(session, msg, &_private_il, keylist, changed_keys);
  29.481      bool _imported_private = false;
  29.482      if (_private_il && _private_il->ident && _private_il->ident->address)
  29.483          _imported_private = true;
  29.484 @@ -3048,7 +3243,7 @@
  29.485      }
  29.486   
  29.487      if (!status) {
  29.488 -        *imported_keys = _imported_keys;
  29.489 +        *keys_were_imported = _keys_were_imported;
  29.490          *imported_private = _imported_private;
  29.491      }
  29.492  
  29.493 @@ -3212,8 +3407,11 @@
  29.494  
  29.495      PEP_STATUS status = PEP_STATUS_OK;
  29.496      
  29.497 -    if (strcasecmp(src->from->address, inner_message->from->address) == 0)
  29.498 +    if (src->from && inner_message->from && 
  29.499 +           src->from->address && inner_message->from->address && 
  29.500 +           strcasecmp(src->from->address, inner_message->from->address) == 0) {
  29.501          status = reconcile_identity(src->from, inner_message->from);
  29.502 +    }    
  29.503      
  29.504      if (status == PEP_STATUS_OK && inner_message->to)
  29.505          status = reconcile_identity_lists(src->to, inner_message->to);
  29.506 @@ -3309,7 +3507,7 @@
  29.507      return NULL;
  29.508  }
  29.509  
  29.510 -static bool import_header_keys(PEP_SESSION session, message* src) {
  29.511 +static bool import_header_keys(PEP_SESSION session, message* src, stringlist_t** imported_key_list, uint64_t* changed_keys) {
  29.512      stringpair_list_t* header_keys = stringpair_list_find(src->opt_fields, "Autocrypt"); 
  29.513      if (!header_keys || !header_keys->value)
  29.514          return false;
  29.515 @@ -3324,7 +3522,12 @@
  29.516      bloblist_t* the_key = base64_str_to_binary_blob(start_key, length);
  29.517      if (!the_key)
  29.518          return false;
  29.519 -    PEP_STATUS status = import_key(session, the_key->value, the_key->size, NULL);
  29.520 +    PEP_STATUS status = _import_key_with_fpr_return(session, 
  29.521 +                                                    the_key->value, 
  29.522 +                                                    the_key->size, 
  29.523 +                                                    NULL, 
  29.524 +                                                    imported_key_list, 
  29.525 +                                                    changed_keys);
  29.526      free_bloblist(the_key);
  29.527      if (status == PEP_STATUS_OK || status == PEP_KEY_IMPORTED)
  29.528          return true;
  29.529 @@ -3470,7 +3673,9 @@
  29.530          stringlist_t **keylist,
  29.531          PEP_rating *rating,
  29.532          PEP_decrypt_flags_t *flags,
  29.533 -        identity_list **private_il
  29.534 +        identity_list **private_il,
  29.535 +        stringlist_t** imported_key_fprs,
  29.536 +        uint64_t* changed_public_keys
  29.537      )
  29.538  {
  29.539      assert(session);
  29.540 @@ -3501,6 +3706,12 @@
  29.541      unsigned int major_ver = 0;
  29.542      unsigned int minor_ver = 0;
  29.543      
  29.544 +    if (imported_key_fprs)
  29.545 +        *imported_key_fprs = NULL;
  29.546 +        
  29.547 +    stringlist_t* _imported_key_list = NULL;
  29.548 +    uint64_t _changed_keys = 0;
  29.549 +    
  29.550      stringpair_list_t* revoke_replace_pairs = NULL;
  29.551      
  29.552      // Grab input flags
  29.553 @@ -3547,17 +3758,26 @@
  29.554      // We really need key used in signing to do anything further on the pEp comm_type.
  29.555      // So we can't adjust the rating of the sender just yet.
  29.556  
  29.557 -    /*** Begin Import any attached public keys and update identities accordingly ***/
  29.558 +    /*** Begin importing any keys attached an outer, undecrypted message - update identities accordingly ***/
  29.559      // Private key in unencrypted mail are ignored -> NULL
  29.560      //
  29.561      // This import is from the outermost message.
  29.562 -    // We don't do this for PGP_mime.
  29.563 -    bool imported_keys = false;
  29.564 +    // We don't do this for PGP_mime. -- KB: FIXME: I am pretty sure this was 
  29.565 +    // because of our overzealous import/remove process, but What does this do to enigmail messages 
  29.566 +    // if the keys are on the outside?? Are they ever?
  29.567 +    bool keys_were_imported = false;
  29.568 +    
  29.569      PEP_cryptotech enc_type = determine_encryption_format(src);
  29.570      if (enc_type != PEP_crypt_OpenPGP || !(src->enc_format == PEP_enc_PGP_MIME || src->enc_format == PEP_enc_PGP_MIME_Outlook1))
  29.571 -        imported_keys = import_attached_keys(session, src, NULL);
  29.572 -            
  29.573 -    import_header_keys(session, src);
  29.574 +        keys_were_imported = import_attached_keys(session, 
  29.575 +                                                  src, NULL, 
  29.576 +                                                  (imported_key_fprs ? &_imported_key_list : NULL), 
  29.577 +                                                  (changed_public_keys ? &_changed_keys : NULL));
  29.578 +    
  29.579 +    // In case there are header keys, also get those
  29.580 +    import_header_keys(session, src, 
  29.581 +                       (imported_key_fprs ? &_imported_key_list : NULL), 
  29.582 +                       (changed_public_keys ? &_changed_keys : NULL));
  29.583      
  29.584      // FIXME: is this really necessary here?
  29.585      // if (src->from) {
  29.586 @@ -3594,7 +3814,7 @@
  29.587          *rating = PEP_rating_unencrypted;
  29.588  
  29.589          // We remove these from the outermost source message
  29.590 -        // if (imported_keys)
  29.591 +        // if (keys_were_imported)
  29.592          //     remove_attached_keys(src);
  29.593                                      
  29.594          pull_up_attached_main_msg(src);
  29.595 @@ -3607,13 +3827,8 @@
  29.596          return status;
  29.597          
  29.598      /** Ok, we should be ready to decrypt. Try decrypt and verify first! **/
  29.599 -    status = cryptotech[crypto].decrypt_and_verify(session, ctext,
  29.600 -                                                   csize, dsig_text, dsig_size,
  29.601 -                                                   &ptext, &psize, &_keylist,
  29.602 -                                                   NULL);
  29.603 -
  29.604 -    if (status == PEP_DECRYPT_NO_KEY)
  29.605 -        signal_Sync_event(session, Sync_PR_keysync, CannotDecrypt, NULL);
  29.606 +    status = decrypt_and_verify(session, ctext, csize, dsig_text, dsig_size,
  29.607 +            &ptext, &psize, &_keylist, NULL);
  29.608  
  29.609      if (status > PEP_CANNOT_DECRYPT_UNKNOWN)
  29.610          goto pEp_error;
  29.611 @@ -3631,7 +3846,7 @@
  29.612              case PEP_enc_PGP_MIME:
  29.613              case PEP_enc_PGP_MIME_Outlook1:
  29.614              
  29.615 -                status = _mime_decode_message_internal(ptext, psize, &msg, &has_inner);
  29.616 +                status = mime_decode_message(ptext, psize, &msg, &has_inner);
  29.617                  if (status != PEP_STATUS_OK)
  29.618                      goto pEp_error;
  29.619                                  
  29.620 @@ -3651,10 +3866,13 @@
  29.621                  //
  29.622                  // We are importing from the decrypted outermost message now.
  29.623                  //
  29.624 -                status = import_priv_keys_from_decrypted_msg(session, msg,
  29.625 -                                                             &imported_keys,
  29.626 -                                                             &imported_private_key_address,
  29.627 -                                                             private_il);
  29.628 +                status = import_keys_from_decrypted_msg(session, msg,
  29.629 +                                                        &keys_were_imported,
  29.630 +                                                        &imported_private_key_address,
  29.631 +                                                        private_il,
  29.632 +                                                        (imported_key_fprs ? &_imported_key_list : NULL), 
  29.633 +                                                        (changed_public_keys ? &_changed_keys : NULL));
  29.634 +                                                        
  29.635                  if (status != PEP_STATUS_OK)
  29.636                      goto pEp_error;            
  29.637  
  29.638 @@ -3672,8 +3890,9 @@
  29.639                  break;
  29.640  
  29.641              case PEP_enc_inline:
  29.642 +            case PEP_enc_inline_EA:
  29.643 +            {
  29.644                  status = PEP_STATUS_OK;
  29.645 -                
  29.646                  _decrypt_in_pieces_status = _decrypt_in_pieces(session, src, &msg, ptext, psize);
  29.647              
  29.648                  switch (_decrypt_in_pieces_status) {
  29.649 @@ -3688,12 +3907,54 @@
  29.650                          goto enomem;
  29.651                      default:
  29.652                          decrypt_status = _decrypt_in_pieces_status;
  29.653 -                        break;
  29.654                  }
  29.655 +
  29.656 +                if (src->enc_format == PEP_enc_inline_EA && msg->longmsg && msg->longmsg[0] == 0) {
  29.657 +                    char *value;
  29.658 +                    size_t size;
  29.659 +                    char *mime_type;
  29.660 +                    const char *filename = NULL;
  29.661 +                    status = decode_internal(ptext, psize, &value, &size, &mime_type);
  29.662 +                    if (status)
  29.663 +                        goto pEp_error;
  29.664 +                    if (strcasecmp(mime_type, "application/pEp.sync") == 0)
  29.665 +                        filename = "file://sync.pEp";
  29.666 +                    else if (strcasecmp(mime_type, "application/pEp.distribution") == 0)
  29.667 +                        filename = "file://distribution.pEp";
  29.668 +                    else if (strcasecmp(mime_type, "application/pgp-keys") == 0)
  29.669 +                        filename = "file://pEpkey.asc";
  29.670 +                    else if (strcasecmp(mime_type, "application/pgp-signature") == 0)
  29.671 +                        filename = "file://electronic_signature.asc";
  29.672 +                    bloblist_t *bl = new_bloblist(value, size, mime_type, filename);
  29.673 +                    free(mime_type);
  29.674 +                    if (bl) {
  29.675 +                        msg->attachments = bl;
  29.676 +                        if (msg->longmsg != ptext)
  29.677 +                            free(msg->longmsg);
  29.678 +                        msg->longmsg = NULL;
  29.679 +                        free(ptext);
  29.680 +                        ptext = NULL;
  29.681 +                        psize = 0;
  29.682 +                    }
  29.683 +                    else {
  29.684 +                        free(value);
  29.685 +                        status = PEP_OUT_OF_MEMORY;
  29.686 +                        goto pEp_error;
  29.687 +                    }
  29.688 +                }
  29.689 +
  29.690 +                status = import_keys_from_decrypted_msg(session, msg,
  29.691 +                                                        &keys_were_imported,
  29.692 +                                                        &imported_private_key_address,
  29.693 +                                                        private_il,
  29.694 +                                                        (imported_key_fprs ? &_imported_key_list : NULL), 
  29.695 +                                                        (changed_public_keys ? &_changed_keys : NULL));
  29.696                  break;
  29.697 +
  29.698              default:
  29.699                  // BUG: must implement more
  29.700                  NOT_IMPLEMENTED
  29.701 +            }
  29.702          }
  29.703  
  29.704          if (status == PEP_OUT_OF_MEMORY)
  29.705 @@ -3766,7 +4027,8 @@
  29.706                  if (message_blob) {              
  29.707                      status = mime_decode_message(message_blob->value, 
  29.708                                                   message_blob->size, 
  29.709 -                                                 &inner_message);
  29.710 +                                                 &inner_message,
  29.711 +                                                 NULL);
  29.712                      if (status != PEP_STATUS_OK)
  29.713                          goto pEp_error;
  29.714                                  
  29.715 @@ -3857,10 +4119,13 @@
  29.716                              private_il = NULL;
  29.717                              
  29.718                              // import keys from decrypted INNER source
  29.719 -                            status = import_priv_keys_from_decrypted_msg(session, inner_message,
  29.720 -                                                                         &imported_keys,
  29.721 -                                                                         &imported_private_key_address,
  29.722 -                                                                         private_il);
  29.723 +                            status = import_keys_from_decrypted_msg(session, inner_message,
  29.724 +                                                                    &keys_were_imported,
  29.725 +                                                                    &imported_private_key_address,
  29.726 +                                                                    private_il,
  29.727 +                                                                    (imported_key_fprs ? &_imported_key_list : NULL), 
  29.728 +                                                                    (changed_public_keys ? &_changed_keys : NULL));
  29.729 +                                                                    
  29.730                              if (status != PEP_STATUS_OK)
  29.731                                  goto pEp_error;            
  29.732                          }
  29.733 @@ -3918,30 +4183,30 @@
  29.734                  
  29.735              } // this we do if this isn't an inner message
  29.736              
  29.737 -            pEp_identity* cs_from = calculated_src->from;
  29.738 -            if (cs_from && !EMPTYSTR(cs_from->address)) {
  29.739 -                if (!is_me(session, cs_from)) {
  29.740 -                    status = update_identity(session, cs_from);
  29.741 +            pEp_identity* msg_from = msg->from;
  29.742 +            if (msg_from && !EMPTYSTR(msg_from->address)) {
  29.743 +                if (!is_me(session, msg_from)) {
  29.744 +                    status = update_identity(session, msg_from);
  29.745                      if (status == PEP_CANNOT_FIND_IDENTITY) {
  29.746 -                        cs_from->user_id = calloc(1, strlen(cs_from->address) + 6);
  29.747 -                        if (!cs_from->user_id)
  29.748 +                        msg_from->user_id = calloc(1, strlen(msg_from->address) + 6);
  29.749 +                        if (!msg_from->user_id)
  29.750                              return PEP_OUT_OF_MEMORY;
  29.751 -                        snprintf(cs_from->user_id, strlen(cs_from->address) + 6,
  29.752 -                                 "TOFU_%s", cs_from->address);        
  29.753 +                        snprintf(msg_from->user_id, strlen(msg_from->address) + 6,
  29.754 +                                 "TOFU_%s", msg_from->address);        
  29.755                          status = PEP_STATUS_OK;
  29.756                      }
  29.757                  }
  29.758                  else {
  29.759                      // update the own from identity, read_only, but preserve username 
  29.760                      // for returned message.
  29.761 -                    char* cached_ownname = cs_from->username;
  29.762 +                    char* cached_ownname = msg_from->username;
  29.763                      // Shouldn't be possible, but just in case.
  29.764                      if (!cached_ownname)
  29.765 -                        cached_ownname = strdup(cs_from->address);
  29.766 -                    cs_from->username = NULL;
  29.767 -                    status = _myself(session, cs_from, false, false, myself_read_only);
  29.768 -                    free(cs_from->username);
  29.769 -                    cs_from->username = cached_ownname;
  29.770 +                        cached_ownname = strdup(msg_from->address);
  29.771 +                    msg_from->username = NULL;
  29.772 +                    status = _myself(session, msg_from, false, false, myself_read_only);
  29.773 +                    free(msg_from->username);
  29.774 +                    msg_from->username = cached_ownname;
  29.775                  }    
  29.776              }                                                                        
  29.777          } // end if (decrypt_status == PEP_DECRYPTED || decrypt_status == PEP_DECRYPTED_AND_VERIFIED)
  29.778 @@ -3952,7 +4217,7 @@
  29.779          // eligible signer comm_types to PEP_ct_pEp_*
  29.780          // This also sets and upgrades pEp version
  29.781          if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED && !is_key_reset && is_pEp_msg && calculated_src->from)
  29.782 -            status = update_sender_to_pEp_trust(session, calculated_src->from, _keylist, major_ver, minor_ver);
  29.783 +            status = update_sender_to_pEp_trust(session, msg->from, _keylist, major_ver, minor_ver);
  29.784  
  29.785          /* Ok, now we have a keylist used for decryption/verification.
  29.786             now we need to update the message rating with the 
  29.787 @@ -3960,7 +4225,7 @@
  29.788             
  29.789          if (!is_key_reset) { // key reset messages invalidate some of the ratings in the DB by now.
  29.790              status = amend_rating_according_to_sender_and_recipients(session,
  29.791 -                     rating, calculated_src->from, _keylist);
  29.792 +                     rating, msg->from, _keylist);
  29.793              if (status != PEP_STATUS_OK)
  29.794                  goto pEp_error;
  29.795           
  29.796 @@ -4008,7 +4273,7 @@
  29.797          decorate_message(msg, *rating, _keylist, false, false);
  29.798  
  29.799          // Maybe unnecessary
  29.800 -        // if (imported_keys)
  29.801 +        // if (keys_were_imported)
  29.802          //     remove_attached_keys(msg);
  29.803                      
  29.804          if (calculated_src->id && calculated_src != msg) {
  29.805 @@ -4019,98 +4284,107 @@
  29.806          }
  29.807      } // End prepare output message for return
  29.808  
  29.809 -    // 3. Check to see if the sender used any of our revoked keys
  29.810 -    if (!is_me(session, msg->from)) {
  29.811 -        status = check_for_own_revoked_key(session, _keylist, &revoke_replace_pairs);
  29.812 -
  29.813 -        //assert(status != PEP_STATUS_OK); // FIXME: FOR DEBUGGING ONLY DO NOT LEAVE IN    
  29.814 -        if (status != PEP_STATUS_OK) {
  29.815 -            // This should really never choke unless the DB is broken.
  29.816 -            status = PEP_UNKNOWN_DB_ERROR;
  29.817 -            goto pEp_error;
  29.818 -        }
  29.819 -        
  29.820 -        if (msg) {
  29.821 -            stringpair_list_t* curr_pair_node;
  29.822 -            stringpair_t* curr_pair;
  29.823 -
  29.824 -            for (curr_pair_node = revoke_replace_pairs; curr_pair_node; curr_pair_node = curr_pair_node->next) {
  29.825 -                curr_pair = curr_pair_node->value;
  29.826 -
  29.827 -                if (!curr_pair)
  29.828 -                    continue; // Again, shouldn't occur
  29.829 -
  29.830 -                if (curr_pair->key && curr_pair->value) {
  29.831 -                    /* Figure out which address(es) this came to so we know who to reply from */                    
  29.832 -
  29.833 -                    identity_list* my_rev_ids = NULL;
  29.834 -                    
  29.835 -                    /* check by replacement ID for identities which used this key? */
  29.836 -                    status = get_identities_by_main_key_id(session, curr_pair->value,
  29.837 -                                                           &my_rev_ids);
  29.838 -                                                                                                                      
  29.839 -                    if (status == PEP_STATUS_OK && my_rev_ids) {
  29.840 -                        // get identities in this list the message was to/cc'd to (not for bcc)
  29.841 -                        identity_list* used_ids_for_key = NULL;
  29.842 -                        status = ident_list_intersect(my_rev_ids, msg->to, &used_ids_for_key);
  29.843 -                        if (status != PEP_STATUS_OK)
  29.844 -                            goto pEp_error; // out of memory
  29.845 -
  29.846 -                        identity_list* used_cc_ids = NULL;    
  29.847 -                        status = ident_list_intersect(my_rev_ids, msg->cc, &used_cc_ids);
  29.848 -                        if (status != PEP_STATUS_OK)
  29.849 -                            goto pEp_error;
  29.850 -
  29.851 -                        used_ids_for_key = identity_list_join(used_ids_for_key, used_cc_ids);
  29.852 -                        
  29.853 -                        identity_list* curr_recip = used_ids_for_key;
  29.854 -                        
  29.855 -                        for ( ; curr_recip && curr_recip->ident; curr_recip = curr_recip->next) {
  29.856 -                            if (!is_me(session, curr_recip->ident))
  29.857 -                                continue;
  29.858 -                        
  29.859 -                            status = create_standalone_key_reset_message(session,
  29.860 -                                &reset_msg,
  29.861 -                                curr_recip->ident,
  29.862 -                                msg->from,
  29.863 -                                curr_pair->key,
  29.864 -                                curr_pair->value);
  29.865 -
  29.866 -                            // If we can't find the identity, this is someone we've never mailed, so we just
  29.867 -                            // go on letting them use the wrong key until we mail them ourselves. (Spammers, etc)
  29.868 -                            if (status != PEP_CANNOT_FIND_IDENTITY) {
  29.869 +    // 3. Check to see if the sender is a pEp user who used any of our revoked keys
  29.870 +    if (msg->from && !is_me(session, msg->from)) {
  29.871 +        bool pEp_peep = false;
  29.872 +
  29.873 +        if (!EMPTYSTR(msg->from->user_id)) {
  29.874 +            status = is_pEp_user(session, msg->from, &pEp_peep);
  29.875 +            
  29.876 +            // If it's a pEp user, check if there was a revoked key used so we can notify
  29.877 +            if (pEp_peep) {
  29.878 +                status = check_for_own_revoked_key(session, _keylist, &revoke_replace_pairs);
  29.879 +
  29.880 +                //assert(status != PEP_STATUS_OK); // FIXME: FOR DEBUGGING ONLY DO NOT LEAVE IN    
  29.881 +                if (status != PEP_STATUS_OK) {
  29.882 +                    // This should really never choke unless the DB is broken.
  29.883 +                    status = PEP_UNKNOWN_DB_ERROR;
  29.884 +                    goto pEp_error;
  29.885 +                }
  29.886 +                
  29.887 +                if (msg) {
  29.888 +                    stringpair_list_t* curr_pair_node;
  29.889 +                    stringpair_t* curr_pair;
  29.890 +
  29.891 +                    for (curr_pair_node = revoke_replace_pairs; curr_pair_node; curr_pair_node = curr_pair_node->next) {
  29.892 +                        curr_pair = curr_pair_node->value;
  29.893 +
  29.894 +                        if (!curr_pair)
  29.895 +                            continue; // Again, shouldn't occur
  29.896 +
  29.897 +                        if (curr_pair->key && curr_pair->value) {
  29.898 +                            /* Figure out which address(es) this came to so we know who to reply from */                    
  29.899 +
  29.900 +                            identity_list* my_rev_ids = NULL;
  29.901 +                            
  29.902 +                            /* check by replacement ID for identities which used this key? */
  29.903 +                            status = get_identities_by_main_key_id(session, curr_pair->value,
  29.904 +                                                                   &my_rev_ids);
  29.905 +                                                                                                                              
  29.906 +                            if (status == PEP_STATUS_OK && my_rev_ids) {
  29.907 +                                // get identities in this list the message was to/cc'd to (not for bcc)
  29.908 +                                identity_list* used_ids_for_key = NULL;
  29.909 +                                status = ident_list_intersect(my_rev_ids, msg->to, &used_ids_for_key);
  29.910 +                                if (status != PEP_STATUS_OK)
  29.911 +                                    goto pEp_error; // out of memory
  29.912 +
  29.913 +                                identity_list* used_cc_ids = NULL;    
  29.914 +                                status = ident_list_intersect(my_rev_ids, msg->cc, &used_cc_ids);
  29.915                                  if (status != PEP_STATUS_OK)
  29.916                                      goto pEp_error;
  29.917  
  29.918 -                                if (!reset_msg) {
  29.919 -                                    status = PEP_OUT_OF_MEMORY;
  29.920 -                                    goto pEp_error;
  29.921 -                                }
  29.922 -                                // insert into queue
  29.923 -                                if (session->messageToSend)
  29.924 -                                    status = session->messageToSend(reset_msg);
  29.925 -                                else
  29.926 -                                    status = PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
  29.927 -
  29.928 -
  29.929 -                                if (status == PEP_STATUS_OK) {
  29.930 -                                    // Put into notified DB
  29.931 -                                    status = set_reset_contact_notified(session, curr_recip->ident->address, curr_pair->key, msg->from->user_id);
  29.932 -                                    if (status != PEP_STATUS_OK) // It's ok to barf because it's a DB problem??
  29.933 -                                        goto pEp_error;
  29.934 -                                }
  29.935 -                                else {
  29.936 -                                    // According to Volker, this would only be a fatal error, so...
  29.937 -                                    free_message(reset_msg); // ??
  29.938 -                                    reset_msg = NULL; // ??
  29.939 -                                    goto pEp_error;
  29.940 -                                }
  29.941 -                            }
  29.942 -                        }    
  29.943 -                    } // else we couldn't find an ident for replacement key    
  29.944 +                                used_ids_for_key = identity_list_join(used_ids_for_key, used_cc_ids);
  29.945 +                                
  29.946 +                                identity_list* curr_recip = used_ids_for_key;
  29.947 +                                
  29.948 +                                for ( ; curr_recip && curr_recip->ident; curr_recip = curr_recip->next) {
  29.949 +                                    if (!is_me(session, curr_recip->ident))
  29.950 +                                        continue;
  29.951 +                                
  29.952 +                                    status = create_standalone_key_reset_message(session,
  29.953 +                                        &reset_msg,
  29.954 +                                        curr_recip->ident,
  29.955 +                                        msg->from,
  29.956 +                                        curr_pair->key,
  29.957 +                                        curr_pair->value);
  29.958 +
  29.959 +                                    // If we can't find the identity, this is someone we've never mailed, so we just
  29.960 +                                    // go on letting them use the wrong key until we mail them ourselves. (Spammers, etc)
  29.961 +                                    if (status != PEP_CANNOT_FIND_IDENTITY) {
  29.962 +                                        if (status != PEP_STATUS_OK)
  29.963 +                                            goto pEp_error;
  29.964 +
  29.965 +                                        if (!reset_msg) {
  29.966 +                                            status = PEP_OUT_OF_MEMORY;
  29.967 +                                            goto pEp_error;
  29.968 +                                        }
  29.969 +                                        // insert into queue
  29.970 +                                        if (session->messageToSend)
  29.971 +                                            status = session->messageToSend(reset_msg);
  29.972 +                                        else
  29.973 +                                            status = PEP_SYNC_NO_MESSAGE_SEND_CALLBACK;
  29.974 +
  29.975 +
  29.976 +                                        if (status == PEP_STATUS_OK) {
  29.977 +                                            // Put into notified DB
  29.978 +                                            status = set_reset_contact_notified(session, curr_recip->ident->address, curr_pair->key, msg->from->user_id);
  29.979 +                                            if (status != PEP_STATUS_OK) // It's ok to barf because it's a DB problem??
  29.980 +                                                goto pEp_error;
  29.981 +                                        }
  29.982 +                                        else {
  29.983 +                                            // According to Volker, this would only be a fatal error, so...
  29.984 +                                            free_message(reset_msg); // ??
  29.985 +                                            reset_msg = NULL; // ??
  29.986 +                                            goto pEp_error;
  29.987 +                                        }
  29.988 +                                    }
  29.989 +                                }    
  29.990 +                            } // else we couldn't find an ident for replacement key    
  29.991 +                        }
  29.992 +                    }        
  29.993                  }
  29.994              }
  29.995 -        }
  29.996 +        }    
  29.997          free_stringpair_list(revoke_replace_pairs);
  29.998          revoke_replace_pairs = NULL;
  29.999      } // end !is_me(msg->from)    
 29.1000 @@ -4204,6 +4478,27 @@
 29.1001          }
 29.1002      }
 29.1003      
 29.1004 +    // by convention
 29.1005 +
 29.1006 +    if (EMPTYSTR(msg->shortmsg) && EMPTYSTR(msg->longmsg) && EMPTYSTR(msg->longmsg_formatted)) {
 29.1007 +        free(msg->shortmsg);
 29.1008 +        msg->shortmsg = strdup("pEp");
 29.1009 +        assert(msg->shortmsg);
 29.1010 +        if (!msg->shortmsg)
 29.1011 +            goto enomem;
 29.1012 +
 29.1013 +        if (src->enc_format == PEP_enc_inline_EA) {
 29.1014 +            stringpair_t *entry = new_stringpair("pEp-auto-consume", "yes");
 29.1015 +            if (!entry)
 29.1016 +                goto enomem;
 29.1017 +            stringpair_list_t * spl = stringpair_list_add(msg->opt_fields, entry);
 29.1018 +            if (!spl)
 29.1019 +                goto enomem;
 29.1020 +            if (!msg->opt_fields)
 29.1021 +                msg->opt_fields = spl;
 29.1022 +        }
 29.1023 +    }
 29.1024 +
 29.1025      // 5. Set up return values
 29.1026      *dst = msg;
 29.1027      *keylist = _keylist;
 29.1028 @@ -4221,6 +4516,11 @@
 29.1029          }
 29.1030      }
 29.1031      
 29.1032 +    if (imported_key_fprs)
 29.1033 +        *imported_key_fprs = _imported_key_list;
 29.1034 +    if (changed_public_keys)
 29.1035 +        *changed_public_keys = _changed_keys;
 29.1036 +    
 29.1037      if (decrypt_status == PEP_DECRYPTED_AND_VERIFIED)
 29.1038          return PEP_STATUS_OK;
 29.1039      else
 29.1040 @@ -4260,8 +4560,13 @@
 29.1041  
 29.1042      if (!(*flags & PEP_decrypt_flag_untrusted_server))
 29.1043          *keylist = NULL;
 29.1044 -    //*keylist = NULL; // NOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO!!!!!! This fucks up reencryption
 29.1045 -    PEP_STATUS status = _decrypt_message(session, src, dst, keylist, rating, flags, NULL);
 29.1046 +        
 29.1047 +    stringlist_t* imported_key_fprs = NULL;
 29.1048 +    uint64_t changed_key_bitvec = 0;    
 29.1049 +        
 29.1050 +    PEP_STATUS status = _decrypt_message(session, src, dst, keylist, 
 29.1051 +                                         rating, flags, NULL,
 29.1052 +                                         &imported_key_fprs, &changed_key_bitvec);
 29.1053  
 29.1054      message *msg = *dst ? *dst : src;
 29.1055  
 29.1056 @@ -4306,6 +4611,7 @@
 29.1057      //         free(sender_fpr);
 29.1058      //     }
 29.1059  
 29.1060 +    free(imported_key_fprs);
 29.1061      return status;
 29.1062  }
 29.1063  
 29.1064 @@ -4325,12 +4631,16 @@
 29.1065      message *dst = NULL;
 29.1066      stringlist_t *keylist = NULL;
 29.1067      PEP_rating rating;
 29.1068 -    PEP_decrypt_flags_t flags;
 29.1069 +    PEP_decrypt_flags_t flags = PEP_decrypt_flag_dont_trigger_sync;
 29.1070  
 29.1071      *ident = NULL;
 29.1072  
 29.1073      identity_list *private_il = NULL;
 29.1074 -    PEP_STATUS status = _decrypt_message(session, msg,  &dst, &keylist, &rating, &flags, &private_il);
 29.1075 +    PEP_STATUS status = _decrypt_message(session, msg,  &dst, 
 29.1076 +                                         &keylist, &rating, 
 29.1077 +                                         &flags, &private_il,
 29.1078 +                                         NULL, NULL); // FIXME - what do we do here? 
 29.1079 +                                                      // I don't think we'd call this if this were still here
 29.1080      free_message(dst);
 29.1081      free_stringlist(keylist);
 29.1082  
 29.1083 @@ -5104,3 +5414,64 @@
 29.1084      free_identity(ident);
 29.1085      return status;
 29.1086  }
 29.1087 +
 29.1088 +PEP_STATUS try_encrypt_message(
 29.1089 +        PEP_SESSION session,
 29.1090 +        message *src,
 29.1091 +        stringlist_t *extra,
 29.1092 +        message **dst,
 29.1093 +        PEP_enc_format enc_format,
 29.1094 +        PEP_encrypt_flags_t flags
 29.1095 +    )
 29.1096 +{
 29.1097 +    PEP_STATUS status = PEP_STATUS_OK;
 29.1098 +
 29.1099 +    assert(session && session->messageToSend && session->notifyHandshake);
 29.1100 +    assert(src && src->from);
 29.1101 +    assert(dst);
 29.1102 +
 29.1103 +    if (!(session && session->messageToSend && session->notifyHandshake && src
 29.1104 +                && src->from && dst))
 29.1105 +        return PEP_ILLEGAL_VALUE;
 29.1106 +
 29.1107 +    if (src->dir == PEP_dir_incoming)
 29.1108 +        return PEP_ILLEGAL_VALUE;
 29.1109 +
 29.1110 +    // https://dev.pep.foundation/Engine/MessageToSendPassphrase
 29.1111 +
 29.1112 +    // first try with empty passphrase
 29.1113 +    char *passphrase = session->curr_passphrase;
 29.1114 +    session->curr_passphrase = NULL;
 29.1115 +    status = encrypt_message(session, src, extra, dst, enc_format, flags);
 29.1116 +    session->curr_passphrase = passphrase;
 29.1117 +
 29.1118 +    // if that worked then that was it
 29.1119 +    if (!(status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE))
 29.1120 +        return status;
 29.1121 +
 29.1122 +    // whithout passphrase we cannot do our job
 29.1123 +    do {
 29.1124 +        // try configured passphrase
 29.1125 +        status = encrypt_message(session, src, extra, dst, enc_format, flags);
 29.1126 +
 29.1127 +        // if the configured passphrase does not work...
 29.1128 +        if (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE) {
 29.1129 +
 29.1130 +            // ... ask the adapter to configure another one
 29.1131 +            PEP_STATUS status2 = session->messageToSend(NULL);
 29.1132 +
 29.1133 +            // if the adapter has no passphrase...
 29.1134 +            if (status2 == PEP_PASSPHRASE_REQUIRED || status2 == PEP_WRONG_PASSPHRASE) {
 29.1135 +
 29.1136 +                // ask the app to configure another one
 29.1137 +                pEp_identity *me = identity_dup(src->from);
 29.1138 +                if (!me)
 29.1139 +                    return PEP_OUT_OF_MEMORY;
 29.1140 +                session->notifyHandshake(me, NULL, SYNC_PASSPHRASE_REQUIRED);
 29.1141 +            }
 29.1142 +        }
 29.1143 +    } while (status == PEP_PASSPHRASE_REQUIRED || status == PEP_WRONG_PASSPHRASE);
 29.1144 +
 29.1145 +    return status;
 29.1146 +}
 29.1147 +
    30.1 --- a/src/message_api.h	Mon Apr 13 13:08:13 2020 +0200
    30.2 +++ b/src/message_api.h	Tue Jul 07 11:53:12 2020 +0200
    30.3 @@ -13,9 +13,11 @@
    30.4  #endif
    30.5  
    30.6  bool import_attached_keys(
    30.7 -        PEP_SESSION session, 
    30.8 +        PEP_SESSION session,
    30.9          message *msg,
   30.10 -        identity_list **private_idents
   30.11 +        identity_list **private_idents, 
   30.12 +        stringlist_t** imported_keys,
   30.13 +        uint64_t* changed_keys
   30.14      );
   30.15  
   30.16  void attach_own_key(PEP_SESSION session, message *msg);
   30.17 @@ -47,7 +49,6 @@
   30.18      // This flag is used to let internal functions know that an encryption 
   30.19      // call is being used as part of a reencryption operation
   30.20      PEP_encrypt_reencrypt = 0x40
   30.21 -    
   30.22  } PEP_encrypt_flags; 
   30.23  
   30.24  typedef unsigned int PEP_encrypt_flags_t;
   30.25 @@ -83,6 +84,13 @@
   30.26  //  caveat:
   30.27  //      the ownership of src remains with the caller
   30.28  //      the ownership of dst goes to the caller
   30.29 +//
   30.30 +//      enc_format PEP_enc_inline_EA:
   30.31 +//          internal format of the encrypted attachments is changing, see
   30.32 +//          https://dev.pep.foundation/Engine/ElevatedAttachments
   30.33 +//
   30.34 +//          Only use this for transports without support for attachments
   30.35 +//          when attached data must be sent inline
   30.36  
   30.37  DYNAMIC_API PEP_STATUS encrypt_message(
   30.38          PEP_SESSION session,
   30.39 @@ -169,26 +177,26 @@
   30.40  
   30.41      // no color
   30.42  
   30.43 -    PEP_rating_cannot_decrypt,
   30.44 -    PEP_rating_have_no_key,
   30.45 -    PEP_rating_unencrypted,
   30.46 -    PEP_rating_unencrypted_for_some, // don't use this any more
   30.47 -    PEP_rating_unreliable,
   30.48 +    PEP_rating_cannot_decrypt = 1,
   30.49 +    PEP_rating_have_no_key = 2,
   30.50 +    PEP_rating_unencrypted = 3,
   30.51 +    PEP_rating_unreliable = 5,
   30.52 +
   30.53 +    PEP_rating_b0rken = -2,
   30.54  
   30.55      // yellow
   30.56  
   30.57 -    PEP_rating_reliable,
   30.58 +    PEP_rating_reliable = 6,
   30.59  
   30.60      // green
   30.61  
   30.62 -    PEP_rating_trusted,
   30.63 -    PEP_rating_trusted_and_anonymized,
   30.64 -    PEP_rating_fully_anonymous,   
   30.65 +    PEP_rating_trusted = 7,
   30.66 +    PEP_rating_trusted_and_anonymized = 8,
   30.67 +    PEP_rating_fully_anonymous = 9, 
   30.68  
   30.69      // red
   30.70  
   30.71      PEP_rating_mistrust = -1,
   30.72 -    PEP_rating_b0rken = -2,
   30.73      PEP_rating_under_attack = -3
   30.74  } PEP_rating;
   30.75  
   30.76 @@ -213,9 +221,10 @@
   30.77      PEP_decrypt_flag_consume = 0x2,
   30.78      PEP_decrypt_flag_ignore = 0x4,
   30.79      PEP_decrypt_flag_src_modified = 0x8,
   30.80 +
   30.81      // input flags    
   30.82      PEP_decrypt_flag_untrusted_server = 0x100,
   30.83 -    PEP_decrypt_flag_dont_trigger_sync = 0x200,
   30.84 +    PEP_decrypt_flag_dont_trigger_sync = 0x200
   30.85  } PEP_decrypt_flags; 
   30.86  
   30.87  typedef unsigned int PEP_decrypt_flags_t;
   30.88 @@ -272,7 +281,10 @@
   30.89  //      the ownership of dst goes to the caller
   30.90  //      the ownership of keylist goes to the caller
   30.91  //      if src is unencrypted this function returns PEP_UNENCRYPTED and sets
   30.92 -//         dst to NULL
   30.93 +//          dst to NULL
   30.94 +//      if src->enc_format is PEP_enc_inline_EA on input then elevated attachments
   30.95 +//          will be expected
   30.96 +
   30.97  DYNAMIC_API PEP_STATUS decrypt_message(
   30.98          PEP_SESSION session,
   30.99          message *src,
  30.100 @@ -535,6 +547,22 @@
  30.101  DYNAMIC_API PEP_rating rating_from_comm_type(PEP_comm_type ct);
  30.102  
  30.103  
  30.104 +// this is the internal function to be used by asynchronous network protocol
  30.105 +// implementations
  30.106 +//
  30.107 +// this function is calling messageToSend(NULL) in case there is a missing or wrong passphrase
  30.108 +//
  30.109 +// do not use it in adapters
  30.110 +
  30.111 +PEP_STATUS try_encrypt_message(
  30.112 +        PEP_SESSION session,
  30.113 +        message *src,
  30.114 +        stringlist_t *extra,
  30.115 +        message **dst,
  30.116 +        PEP_enc_format enc_format,
  30.117 +        PEP_encrypt_flags_t flags
  30.118 +    );
  30.119 +
  30.120  #ifdef __cplusplus
  30.121  }
  30.122  #endif
    31.1 --- a/src/mime.c	Mon Apr 13 13:08:13 2020 +0200
    31.2 +++ b/src/mime.c	Tue Jul 07 11:53:12 2020 +0200
    31.3 @@ -32,12 +32,3 @@
    31.4  
    31.5      return strncmp(text, "-----BEGIN PGP MESSAGE-----", 27) == 0;
    31.6  }
    31.7 -
    31.8 -DYNAMIC_API PEP_STATUS mime_encode_message(
    31.9 -        const message * msg,
   31.10 -        bool omit_fields,
   31.11 -        char **mimetext
   31.12 -    )
   31.13 -{
   31.14 -    return _mime_encode_message_internal(msg, omit_fields, mimetext, true, false);
   31.15 -}
    32.1 --- a/src/mime.h	Mon Apr 13 13:08:13 2020 +0200
    32.2 +++ b/src/mime.h	Tue Jul 07 11:53:12 2020 +0200
    32.3 @@ -23,9 +23,21 @@
    32.4  // mime_encode_message() - encode a MIME message
    32.5  //
    32.6  //  parameters:
    32.7 -//      msg (in)                message to encode
    32.8 -//      omit_fields (in)        only encode message body and attachments
    32.9 -//      mimetext (out)          the resulting encoded text or NULL on any error
   32.10 +//      msg (in)                       message to encode
   32.11 +//      omit_fields (in)               only encode message body and 
   32.12 +//                                     attachments
   32.13 +//      mimetext (out)                 the resulting encoded text or 
   32.14 +//                                     NULL on any error
   32.15 +//      has_pEp_msg_attachment (in)    is the first *attachment* to this 
   32.16 +//                                     message an embedded pEp message
   32.17 +//                                     which needs appropriate marking
   32.18 +//                                     (forwarded=no, etc) and encoding?
   32.19 +//                                     (this argument is internal to 
   32.20 +//                                     pEp and should almost
   32.21 +//                                     ALWAYS be false when used 
   32.22 +//                                     by external callers, including
   32.23 +//                                     adapters!!!)
   32.24 +//                                  
   32.25  //
   32.26  //  return value:
   32.27  //      PEP_STATUS_OK           if everything worked
   32.28 @@ -48,16 +60,24 @@
   32.29  DYNAMIC_API PEP_STATUS mime_encode_message(
   32.30          const message * msg,
   32.31          bool omit_fields,
   32.32 -        char **mimetext
   32.33 +        char **mimetext,
   32.34 +        bool has_pEp_msg_attachment     
   32.35      );
   32.36  
   32.37  
   32.38  // mime_decode_message() - decode a MIME message
   32.39  //
   32.40  //  parameters:
   32.41 -//      mimetext (in)           	MIME encoded text to decode
   32.42 -//      size (in)               	size of text to decode
   32.43 -//      msg (out)               	decoded message
   32.44 +//      mimetext (in)           	   MIME encoded text to decode
   32.45 +//      size (in)               	   size of text to decode
   32.46 +//      msg (out)               	   decoded message
   32.47 +//      has_possible_pEp_msg (inout)   If non-NULL, will return 
   32.48 +//                                     true when the first attachment 
   32.49 +//                                     is a potential pEp message
   32.50 +//                                     (mime-type = message/rfc822 and 
   32.51 +//                                     content-disposition parameter
   32.52 +//                                     forwarded=no) 
   32.53 +//      
   32.54  //
   32.55  //  return value:
   32.56  //      PEP_STATUS_OK           if everything worked
   32.57 @@ -75,27 +95,10 @@
   32.58  DYNAMIC_API PEP_STATUS mime_decode_message(
   32.59          const char *mimetext,
   32.60          size_t size,
   32.61 -        message **msg
   32.62 +        message **msg,
   32.63 +        bool* has_possible_pEp_msg
   32.64      );
   32.65  
   32.66 -/* Carries extra return argument letting message api know if it needs to raise the attachment as 2.0/2.1 */
   32.67 -PEP_STATUS _mime_decode_message_internal(
   32.68 -        const char *mimetext,
   32.69 -        size_t size,
   32.70 -        message **msg,
   32.71 -        bool* raise_msg_attachment
   32.72 -    );
   32.73 -
   32.74 -/* sometimes we don't want to transport encode */
   32.75 -PEP_STATUS _mime_encode_message_internal(
   32.76 -        const message * msg,
   32.77 -        bool omit_fields,
   32.78 -        char **mimetext,
   32.79 -        bool transport_encode,
   32.80 -        bool set_attachment_forward_comment        
   32.81 -    );
   32.82 -
   32.83 -
   32.84  #ifdef __cplusplus
   32.85  }
   32.86  #endif
    33.1 --- a/src/pEpEngine.c	Mon Apr 13 13:08:13 2020 +0200
    33.2 +++ b/src/pEpEngine.c	Tue Jul 07 11:53:12 2020 +0200
    33.3 @@ -82,11 +82,11 @@
    33.4  static const char *sql_get_identity =  
    33.5      "select identity.main_key_id, username, comm_type, lang,"
    33.6      "   identity.flags | pgp_keypair.flags,"
    33.7 -    "   is_own, pEp_version_major, pEp_version_minor"
    33.8 +    "   is_own, pEp_version_major, pEp_version_minor, enc_format"
    33.9      "   from identity"
   33.10      "   join person on id = identity.user_id"
   33.11 -    "   join pgp_keypair on fpr = identity.main_key_id"
   33.12 -    "   join trust on id = trust.user_id"
   33.13 +    "   left join pgp_keypair on fpr = identity.main_key_id"
   33.14 +    "   left join trust on id = trust.user_id"
   33.15      "       and pgp_keypair_fpr = identity.main_key_id"    
   33.16      "   where (case when (address = ?1) then (1)"
   33.17      "               when (lower(address) = lower(?1)) then (1)"
   33.18 @@ -100,11 +100,11 @@
   33.19  static const char *sql_get_identities_by_main_key_id =  
   33.20      "select address, identity.user_id, username, comm_type, lang,"
   33.21      "   identity.flags | pgp_keypair.flags,"
   33.22 -    "   is_own, pEp_version_major, pEp_version_minor"
   33.23 +    "   is_own, pEp_version_major, pEp_version_minor, enc_format"
   33.24      "   from identity"
   33.25      "   join person on id = identity.user_id"
   33.26 -    "   join pgp_keypair on fpr = identity.main_key_id"
   33.27 -    "   join trust on id = trust.user_id"
   33.28 +    "   left join pgp_keypair on fpr = identity.main_key_id"
   33.29 +    "   left join trust on id = trust.user_id"
   33.30      "       and pgp_keypair_fpr = identity.main_key_id"    
   33.31      "   where identity.main_key_id = ?1" 
   33.32      "   order by is_own desc, "
   33.33 @@ -112,7 +112,7 @@
   33.34  
   33.35  static const char *sql_get_identity_without_trust_check =  
   33.36      "select identity.main_key_id, username, lang,"
   33.37 -    "   identity.flags, is_own, pEp_version_major, pEp_version_minor"
   33.38 +    "   identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format"
   33.39      "   from identity"
   33.40      "   join person on id = identity.user_id"
   33.41      "   where (case when (address = ?1) then (1)"
   33.42 @@ -126,7 +126,7 @@
   33.43  
   33.44  static const char *sql_get_identities_by_address =  
   33.45      "select user_id, identity.main_key_id, username, lang,"
   33.46 -    "   identity.flags, is_own, pEp_version_major, pEp_version_minor"
   33.47 +    "   identity.flags, is_own, pEp_version_major, pEp_version_minor, enc_format"
   33.48      "   from identity"
   33.49      "   join person on id = identity.user_id"
   33.50      "   where (case when (address = ?1) then (1)"
   33.51 @@ -140,11 +140,11 @@
   33.52  static const char *sql_get_identities_by_userid =  
   33.53      "select address, identity.main_key_id, username, comm_type, lang,"
   33.54      "   identity.flags | pgp_keypair.flags,"
   33.55 -    "   is_own, pEp_version_major, pEp_version_minor"
   33.56 +    "   is_own, pEp_version_major, pEp_version_minor, enc_format"
   33.57      "   from identity"
   33.58      "   join person on id = identity.user_id"
   33.59 -    "   join pgp_keypair on fpr = identity.main_key_id"
   33.60 -    "   join trust on id = trust.user_id"
   33.61 +    "   left join pgp_keypair on fpr = identity.main_key_id"
   33.62 +    "   left join trust on id = trust.user_id"
   33.63      "       and pgp_keypair_fpr = identity.main_key_id"    
   33.64      "   where identity.user_id = ?1" 
   33.65      "   order by is_own desc, "
   33.66 @@ -155,10 +155,12 @@
   33.67      "   set main_key_id = ?1 "
   33.68      "   where main_key_id = ?2 ;";
   33.69      
   33.70 -static const char *sql_remove_fpr_as_default =
   33.71 -    "update person set main_key_id = NULL where main_key_id = ?1 ;"
   33.72 +static const char *sql_remove_fpr_as_identity_default =
   33.73      "update identity set main_key_id = NULL where main_key_id = ?1 ;";
   33.74  
   33.75 +static const char *sql_remove_fpr_as_user_default =
   33.76 +    "update person set main_key_id = NULL where main_key_id = ?1 ;";
   33.77 +    
   33.78  // Set person, but if already exist, only update.
   33.79  // if main_key_id already set, don't touch.
   33.80  static const char *sql_set_person = 
   33.81 @@ -310,6 +312,16 @@
   33.82      "          end) = 1"
   33.83      "          and user_id = ?3 ;";
   33.84  
   33.85 +static const char *sql_set_ident_enc_format =
   33.86 +    "update identity "
   33.87 +    "   set enc_format = ?1 "
   33.88 +    "   where (case when (address = ?2) then (1)"
   33.89 +    "               when (lower(address) = lower(?2)) then (1)"
   33.90 +    "               when (replace(lower(address),'.','') = replace(lower(?2),'.','')) then (1) "
   33.91 +    "               else 0 "
   33.92 +    "          end) = 1 "
   33.93 +    "          and user_id = ?3 ;";
   33.94 +
   33.95  static const char *sql_set_pEp_version =
   33.96      "update identity "
   33.97      "   set pEp_version_major = ?1, "
   33.98 @@ -431,14 +443,14 @@
   33.99      "   lang, identity.flags | pgp_keypair.flags, pEp_version_major, pEp_version_minor"
  33.100      "   from identity"
  33.101      "   join person on id = identity.user_id"
  33.102 -    "   join pgp_keypair on fpr = identity.main_key_id"
  33.103 -    "   join trust on id = trust.user_id"
  33.104 +    "   left join pgp_keypair on fpr = identity.main_key_id"
  33.105 +    "   left join trust on id = trust.user_id"
  33.106      "       and pgp_keypair_fpr = identity.main_key_id"
  33.107      "   where identity.is_own = 1"
  33.108      "       and (identity.flags & ?1) = 0;";
  33.109  
  33.110  static const char *sql_own_keys_retrieve = 
  33.111 -    "select pgp_keypair_fpr from trust"
  33.112 +    "select distinct pgp_keypair_fpr from trust"
  33.113      "   join identity on trust.user_id = identity.user_id"
  33.114      "   where identity.is_own = 1";
  33.115  
  33.116 @@ -454,7 +466,7 @@
  33.117      "select id from person"
  33.118      "   join identity on id = identity.user_id"
  33.119      "   where identity.is_own = 1";
  33.120 -
  33.121 +    
  33.122  // Sequence
  33.123  static const char *sql_sequence_value1 = 
  33.124      "insert or replace into sequences (name, value) "
  33.125 @@ -1056,7 +1068,7 @@
  33.126      sqlite3_busy_timeout(_session->system_db, 1000);
  33.127  
  33.128  // increment this when patching DDL
  33.129 -#define _DDL_USER_VERSION "13"
  33.130 +#define _DDL_USER_VERSION "14"
  33.131  
  33.132      if (in_first) {
  33.133  
  33.134 @@ -1118,7 +1130,8 @@
  33.135                  "   flags integer default 0,\n"
  33.136                  "   is_own integer default 0,\n"
  33.137                  "   pEp_version_major integer default 0,\n"
  33.138 -                "   pEp_version_minor integer default 0,\n"                
  33.139 +                "   pEp_version_minor integer default 0,\n"
  33.140 +                "   enc_format integer default 0,\n"               
  33.141                  "   timestamp integer default (datetime('now')),\n"
  33.142                  "   primary key (address, user_id)\n"
  33.143                  ");\n"
  33.144 @@ -1230,7 +1243,10 @@
  33.145          // Sometimes the user_version wasn't set correctly. 
  33.146          if (version == 1) {
  33.147              bool version_changed = true;
  33.148 -            if (table_contains_column(_session, "revocation_contact_list", "own_address")) {
  33.149 +            if (table_contains_column(_session, "identity", "enc_format")) {
  33.150 +                version = 14;
  33.151 +            }
  33.152 +            else if (table_contains_column(_session, "revocation_contact_list", "own_address")) {
  33.153                  version = 13;
  33.154              }
  33.155              else if (table_contains_column(_session, "identity", "pEp_version_major")) {
  33.156 @@ -1690,7 +1706,19 @@
  33.157                  assert(status == PEP_STATUS_OK);
  33.158                  if (status != PEP_STATUS_OK)
  33.159                      return status;
  33.160 -            }        
  33.161 +            }
  33.162 +            if (version < 14) {
  33.163 +                int_result = sqlite3_exec(
  33.164 +                    _session->db,
  33.165 +                    "alter table identity\n"
  33.166 +                    "   add column enc_format integer default 0;\n",
  33.167 +                    NULL,
  33.168 +                    NULL,
  33.169 +                    NULL
  33.170 +                );
  33.171 +                assert(int_result == SQLITE_OK);
  33.172 +            }
  33.173 +                    
  33.174          }        
  33.175          else { 
  33.176              // Version from DB was 0, it means this is initial setup.
  33.177 @@ -1797,9 +1825,14 @@
  33.178              &_session->replace_identities_fpr, NULL);
  33.179      assert(int_result == SQLITE_OK);
  33.180      
  33.181 -    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_default,
  33.182 -            (int)strlen(sql_remove_fpr_as_default), 
  33.183 -            &_session->remove_fpr_as_default, NULL);
  33.184 +    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_identity_default,
  33.185 +            (int)strlen(sql_remove_fpr_as_identity_default), 
  33.186 +            &_session->remove_fpr_as_identity_default, NULL);
  33.187 +    assert(int_result == SQLITE_OK);
  33.188 +
  33.189 +    int_result = sqlite3_prepare_v2(_session->db, sql_remove_fpr_as_user_default,
  33.190 +            (int)strlen(sql_remove_fpr_as_user_default), 
  33.191 +            &_session->remove_fpr_as_user_default, NULL);
  33.192      assert(int_result == SQLITE_OK);
  33.193  
  33.194      int_result = sqlite3_prepare_v2(_session->db, sql_set_person,
  33.195 @@ -1899,6 +1932,11 @@
  33.196              NULL);
  33.197      assert(int_result == SQLITE_OK);
  33.198  
  33.199 +    int_result = sqlite3_prepare_v2(_session->db, sql_set_ident_enc_format,
  33.200 +            (int)strlen(sql_set_ident_enc_format), &_session->set_ident_enc_format,
  33.201 +            NULL);
  33.202 +    assert(int_result == SQLITE_OK);
  33.203 +            
  33.204      int_result = sqlite3_prepare_v2(_session->db, sql_set_pEp_version,
  33.205              (int)strlen(sql_set_pEp_version), &_session->set_pEp_version,
  33.206              NULL);
  33.207 @@ -2061,6 +2099,11 @@
  33.208          goto pEp_error;
  33.209  
  33.210      // runtime config
  33.211 +    
  33.212 +    // clean up invalid keys 
  33.213 +    status = clean_own_key_defaults(_session);
  33.214 +    if (status != PEP_STATUS_OK)
  33.215 +        goto pEp_error;
  33.216  
  33.217      *session = _session;
  33.218      
  33.219 @@ -2126,8 +2169,10 @@
  33.220                  sqlite3_finalize(session->add_userid_alias);
  33.221              if (session->replace_identities_fpr)
  33.222                  sqlite3_finalize(session->replace_identities_fpr);        
  33.223 -            if (session->remove_fpr_as_default)
  33.224 -                sqlite3_finalize(session->remove_fpr_as_default);            
  33.225 +            if (session->remove_fpr_as_identity_default)
  33.226 +                sqlite3_finalize(session->remove_fpr_as_identity_default);            
  33.227 +            if (session->remove_fpr_as_user_default)
  33.228 +                sqlite3_finalize(session->remove_fpr_as_user_default);            
  33.229              if (session->set_person)
  33.230                  sqlite3_finalize(session->set_person);
  33.231              if (session->delete_person)
  33.232 @@ -2166,6 +2211,8 @@
  33.233                  sqlite3_finalize(session->set_identity_flags);
  33.234              if (session->unset_identity_flags)
  33.235                  sqlite3_finalize(session->unset_identity_flags);
  33.236 +            if (session->set_ident_enc_format)
  33.237 +                sqlite3_finalize(session->set_ident_enc_format);
  33.238              if (session->set_pEp_version)
  33.239                  sqlite3_finalize(session->set_pEp_version);                
  33.240              if (session->exists_trust_entry)
  33.241 @@ -2281,6 +2328,41 @@
  33.242          session->unencrypted_subject = enable;
  33.243  }
  33.244  
  33.245 +DYNAMIC_API PEP_STATUS config_passphrase(PEP_SESSION session, const char *passphrase) {
  33.246 +    if (!session)
  33.247 +        return PEP_ILLEGAL_VALUE;
  33.248 +        
  33.249 +    PEP_STATUS status = PEP_STATUS_OK;
  33.250 +    free(session->curr_passphrase);
  33.251 +    if (!passphrase)
  33.252 +        session->curr_passphrase = NULL;
  33.253 +    else {
  33.254 +        session->curr_passphrase = strdup(passphrase);
  33.255 +        if (!session->curr_passphrase)
  33.256 +            status = PEP_OUT_OF_MEMORY;
  33.257 +    }
  33.258 +    return status;
  33.259 +}
  33.260 +
  33.261 +DYNAMIC_API PEP_STATUS config_passphrase_for_new_keys(PEP_SESSION session, bool enable, const char *passphrase) {
  33.262 +    if (enable && EMPTYSTR(passphrase))
  33.263 +        return PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED;
  33.264 +        
  33.265 +    session->new_key_pass_enable = enable;
  33.266 +    PEP_STATUS status = PEP_STATUS_OK;
  33.267 +
  33.268 +    free(session->generation_passphrase);
  33.269 +    if (!passphrase)
  33.270 +        session->generation_passphrase = NULL;
  33.271 +    else {
  33.272 +        session->generation_passphrase = strdup(passphrase);
  33.273 +        if (!session->generation_passphrase)
  33.274 +            status = PEP_OUT_OF_MEMORY;
  33.275 +    }
  33.276 +    return status;    
  33.277 +}
  33.278 +
  33.279 +
  33.280  DYNAMIC_API void config_service_log(PEP_SESSION session, bool enable)
  33.281  {
  33.282      assert(session);
  33.283 @@ -2756,7 +2838,8 @@
  33.284              sqlite3_column_int(session->get_identity, 6);
  33.285          _identity->minor_ver =
  33.286              sqlite3_column_int(session->get_identity, 7);
  33.287 -    
  33.288 +        _identity->enc_format =    
  33.289 +            sqlite3_column_int(session->get_identity, 8);    
  33.290          *identity = _identity;
  33.291          break;
  33.292      default:
  33.293 @@ -2834,6 +2917,9 @@
  33.294              sqlite3_column_int(session->get_identities_by_userid, 7);
  33.295          ident->minor_ver =
  33.296              sqlite3_column_int(session->get_identities_by_userid, 8);
  33.297 +        ident->enc_format =    
  33.298 +            sqlite3_column_int(session->get_identities_by_userid, 9);    
  33.299 +            
  33.300      
  33.301          identity_list_add(*identities, ident);
  33.302          ident = NULL;
  33.303 @@ -2904,6 +2990,8 @@
  33.304              sqlite3_column_int(session->get_identities_by_main_key_id, 7);
  33.305          ident->minor_ver =
  33.306              sqlite3_column_int(session->get_identities_by_main_key_id, 8);
  33.307 +        ident->enc_format =    
  33.308 +            sqlite3_column_int(session->get_identities_by_main_key_id, 9);                
  33.309      
  33.310          identity_list_add(*identities, ident);
  33.311          ident = NULL;
  33.312 @@ -2978,6 +3066,8 @@
  33.313              sqlite3_column_int(session->get_identity_without_trust_check, 5);
  33.314          _identity->minor_ver =
  33.315              sqlite3_column_int(session->get_identity_without_trust_check, 6);
  33.316 +        _identity->enc_format =    
  33.317 +            sqlite3_column_int(session->get_identity_without_trust_check, 7);                
  33.318      
  33.319          *identity = _identity;
  33.320          break;
  33.321 @@ -3047,7 +3137,9 @@
  33.322              sqlite3_column_int(session->get_identities_by_address, 6);
  33.323          ident->minor_ver =
  33.324              sqlite3_column_int(session->get_identities_by_address, 7);
  33.325 -    
  33.326 +        ident->enc_format =    
  33.327 +            sqlite3_column_int(session->get_identities_by_address, 8);               
  33.328 +                 
  33.329          if (ident_list)
  33.330              identity_list_add(ident_list, ident);
  33.331          else
  33.332 @@ -3795,16 +3887,26 @@
  33.333      if (!session || !fpr)
  33.334          return PEP_ILLEGAL_VALUE;
  33.335              
  33.336 -    sqlite3_reset(session->remove_fpr_as_default);
  33.337 -    sqlite3_bind_text(session->remove_fpr_as_default, 1, fpr, -1,
  33.338 +    sqlite3_reset(session->remove_fpr_as_identity_default);
  33.339 +    sqlite3_bind_text(session->remove_fpr_as_identity_default, 1, fpr, -1,
  33.340                        SQLITE_STATIC);
  33.341  
  33.342 -    int result = sqlite3_step(session->remove_fpr_as_default);
  33.343 -    sqlite3_reset(session->remove_fpr_as_default);
  33.344 +    int result = sqlite3_step(session->remove_fpr_as_identity_default);
  33.345 +    sqlite3_reset(session->remove_fpr_as_identity_default);
  33.346      
  33.347      if (result != SQLITE_DONE)
  33.348 -        return PEP_CANNOT_SET_IDENTITY; // misleading - could also be person
  33.349 -
  33.350 +        return PEP_CANNOT_SET_IDENTITY; 
  33.351 +
  33.352 +    sqlite3_reset(session->remove_fpr_as_user_default);
  33.353 +    sqlite3_bind_text(session->remove_fpr_as_user_default, 1, fpr, -1,
  33.354 +                      SQLITE_STATIC);
  33.355 +
  33.356 +    result = sqlite3_step(session->remove_fpr_as_user_default);
  33.357 +    sqlite3_reset(session->remove_fpr_as_user_default);
  33.358 +    
  33.359 +    if (result != SQLITE_DONE)
  33.360 +        return PEP_CANNOT_SET_PERSON; 
  33.361 +        
  33.362      return PEP_STATUS_OK;
  33.363  }
  33.364  
  33.365 @@ -3919,6 +4021,38 @@
  33.366      return PEP_STATUS_OK;
  33.367  }
  33.368  
  33.369 +DYNAMIC_API PEP_STATUS set_ident_enc_format(
  33.370 +        PEP_SESSION session,
  33.371 +        pEp_identity *identity,
  33.372 +        PEP_enc_format format
  33.373 +    )
  33.374 +{
  33.375 +    int result;
  33.376 +
  33.377 +    assert(session);
  33.378 +    assert(identity);
  33.379 +    assert(identity->address);
  33.380 +    assert(identity->user_id);
  33.381 +
  33.382 +    if (!(session && identity && identity->address && identity->user_id))
  33.383 +        return PEP_ILLEGAL_VALUE;
  33.384 +
  33.385 +    sqlite3_reset(session->set_ident_enc_format);
  33.386 +    sqlite3_bind_int(session->set_ident_enc_format, 1, format);
  33.387 +    sqlite3_bind_text(session->set_ident_enc_format, 2, identity->address, -1,
  33.388 +            SQLITE_STATIC);
  33.389 +    sqlite3_bind_text(session->set_ident_enc_format, 3, identity->user_id, -1,
  33.390 +        SQLITE_STATIC);
  33.391 +        
  33.392 +    result = sqlite3_step(session->set_ident_enc_format);
  33.393 +
  33.394 +    sqlite3_reset(session->set_ident_enc_format);
  33.395 +    if (result != SQLITE_DONE)
  33.396 +        return PEP_CANNOT_SET_IDENTITY;
  33.397 +
  33.398 +    return PEP_STATUS_OK;
  33.399 +}
  33.400 +
  33.401  PEP_STATUS get_trust_by_userid(PEP_SESSION session, const char* user_id,
  33.402                                             labeled_int_list_t** trust_list)
  33.403  {
  33.404 @@ -4347,7 +4481,7 @@
  33.405                                            const char* new_fpr, const char* compare_fpr) {
  33.406      assert(session);
  33.407      assert(user_id);
  33.408 -    assert(new_fpr);
  33.409 +    assert(compare_fpr);
  33.410      
  33.411      if (!session || !user_id || !compare_fpr)
  33.412          return PEP_ILLEGAL_VALUE;
  33.413 @@ -4448,11 +4582,15 @@
  33.414      return PEP_STATUS_OK;
  33.415  }
  33.416  
  33.417 -void pEp_free(void *p)
  33.418 +DYNAMIC_API void pEp_free(void *p)
  33.419  {
  33.420      free(p);
  33.421  }
  33.422  
  33.423 +DYNAMIC_API void *pEp_realloc(void *p, size_t size)
  33.424 +{
  33.425 +    return realloc(p, size);
  33.426 +}
  33.427  
  33.428  DYNAMIC_API PEP_STATUS get_trust(PEP_SESSION session, pEp_identity *identity)
  33.429  {
  33.430 @@ -4534,6 +4672,26 @@
  33.431      return status;
  33.432  }
  33.433  
  33.434 +static void sanitize_pgp_filename(char *filename)
  33.435 +{
  33.436 +    for (int i=0; filename[i]; ++i) {
  33.437 +        switch(filename[i]) {
  33.438 +            // path separators
  33.439 +            case '/':
  33.440 +            case ':':
  33.441 +            case '\\':
  33.442 +            // expansion operators
  33.443 +            case '%':
  33.444 +            case '$':
  33.445 +            // code execution operators
  33.446 +            case '`':
  33.447 +            case '|':
  33.448 +                filename[i] = '-';
  33.449 +                break;
  33.450 +        }
  33.451 +    }
  33.452 +}
  33.453 +
  33.454  DYNAMIC_API PEP_STATUS decrypt_and_verify(
  33.455      PEP_SESSION session, const char *ctext, size_t csize,
  33.456      const char *dsigtext, size_t dsigsize,
  33.457 @@ -4558,6 +4716,9 @@
  33.458      if (status == PEP_DECRYPT_NO_KEY)
  33.459          signal_Sync_event(session, Sync_PR_keysync, CannotDecrypt, NULL);
  33.460  
  33.461 +    if (filename_ptr && *filename_ptr)
  33.462 +        sanitize_pgp_filename(*filename_ptr);
  33.463 +
  33.464      return status;
  33.465  }
  33.466  
  33.467 @@ -4802,7 +4963,18 @@
  33.468          PEP_SESSION session,
  33.469          const char *key_data,
  33.470          size_t size,
  33.471 -        identity_list **private_keys
  33.472 +        identity_list **private_keys)
  33.473 +{
  33.474 +    return _import_key_with_fpr_return(session, key_data, size, private_keys, NULL, NULL);
  33.475 +}
  33.476 +
  33.477 +PEP_STATUS _import_key_with_fpr_return(
  33.478 +        PEP_SESSION session,
  33.479 +        const char *key_data,
  33.480 +        size_t size,
  33.481 +        identity_list **private_keys,
  33.482 +        stringlist_t** imported_keys,
  33.483 +        uint64_t* changed_public_keys        
  33.484      )
  33.485  {
  33.486      assert(session);
  33.487 @@ -4810,9 +4982,12 @@
  33.488  
  33.489      if (!(session && key_data))
  33.490          return PEP_ILLEGAL_VALUE;
  33.491 +        
  33.492 +    if (imported_keys && !*imported_keys && changed_public_keys)
  33.493 +        *changed_public_keys = 0;
  33.494  
  33.495      return session->cryptotech[PEP_crypt_OpenPGP].import_key(session, key_data,
  33.496 -            size, private_keys);
  33.497 +            size, private_keys, imported_keys, changed_public_keys);
  33.498  }
  33.499  
  33.500  DYNAMIC_API PEP_STATUS recv_key(PEP_SESSION session, const char *pattern)
    34.1 --- a/src/pEpEngine.h	Mon Apr 13 13:08:13 2020 +0200
    34.2 +++ b/src/pEpEngine.h	Tue Jul 07 11:53:12 2020 +0200
    34.3 @@ -17,7 +17,18 @@
    34.4  #include "labeled_int_list.h"    
    34.5  #include "timestamp.h"
    34.6  
    34.7 -#define PEP_VERSION "2.1" // protocol version
    34.8 +#define PEP_VERSION "2.1" // pEp *protocol* version
    34.9 +
   34.10 +// RELEASE version this targets
   34.11 +// (string: major.minor.patch)
   34.12 +#define PEP_ENGINE_VERSION "2.1.0"
   34.13 +
   34.14 +// Numeric values of above:
   34.15 +#define PEP_ENGINE_VERSION_MAJOR 2
   34.16 +#define PEP_ENGINE_VERSION_MINOR 1
   34.17 +#define PEP_ENGINE_VERSION_PATCH 0
   34.18 +#define PEP_ENGINE_VERSION_RC    11
   34.19 +
   34.20  
   34.21  #define PEP_OWN_USERID "pEp_own_userId"
   34.22      
   34.23 @@ -121,6 +132,10 @@
   34.24      PEP_STATEMACHINE_INHIBITED_EVENT                = 0x0986,
   34.25      PEP_STATEMACHINE_CANNOT_SEND                    = 0x0987,
   34.26  
   34.27 +    PEP_PASSPHRASE_REQUIRED                         = 0x0a00,
   34.28 +    PEP_WRONG_PASSPHRASE                            = 0x0a01,
   34.29 +    PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED            = 0x0a02,
   34.30 +
   34.31      PEP_DISTRIBUTION_ILLEGAL_MESSAGE                = 0x1002,
   34.32  
   34.33      PEP_COMMIT_FAILED                               = 0xff01,
   34.34 @@ -138,6 +153,18 @@
   34.35      PEP_VERSION_MISMATCH                            = -7,
   34.36  } PEP_STATUS;
   34.37  
   34.38 +typedef enum _PEP_enc_format {
   34.39 +    PEP_enc_none = 0,                       // message is not encrypted
   34.40 +    PEP_enc_pieces = 1,                     // inline PGP + PGP extensions, was removed
   34.41 +    PEP_enc_inline = 1,                     // still there
   34.42 +    PEP_enc_S_MIME,                         // RFC5751
   34.43 +    PEP_enc_PGP_MIME,                       // RFC3156
   34.44 +    PEP_enc_PEP,                            // pEp encryption format
   34.45 +    PEP_enc_PGP_MIME_Outlook1,              // Message B0rken by Outlook type 1
   34.46 +    PEP_enc_inline_EA,
   34.47 +    PEP_enc_auto = 255                      // figure out automatically where possible
   34.48 +} PEP_enc_format;
   34.49 +
   34.50  
   34.51  // messageToSend() - a message needs to be delivered by application
   34.52  //
   34.53 @@ -609,8 +636,9 @@
   34.54      char lang[3];               // language of conversation
   34.55                                  // ISO 639-1 ALPHA-2, last byte is 0
   34.56      bool me;                    // if this is the local user herself/himself
   34.57 -    unsigned int major_ver;              // highest version of pEp message received, if any
   34.58 -    unsigned int minor_ver;              // highest version of pEp message received, if any
   34.59 +    unsigned int major_ver;     // highest version of pEp message received, if any
   34.60 +    unsigned int minor_ver;     // highest version of pEp message received, if any
   34.61 +    PEP_enc_format enc_format;  // Last specified format we encrypted to for this identity
   34.62      identity_flags_t flags;     // identity_flag1 | identity_flag2 | ...
   34.63  } pEp_identity;
   34.64  
   34.65 @@ -884,10 +912,11 @@
   34.66  // import_key() - import key from data
   34.67  //
   34.68  //  parameters:
   34.69 -//      session (in)            session handle
   34.70 -//      key_data (in)           key data, i.e. ASCII armored OpenPGP key
   34.71 -//      size (in)               amount of data to handle
   34.72 -//      private_keys (out)      list of private keys that have been imported
   34.73 +//      session (in)                session handle
   34.74 +//      key_data (in)               key data, i.e. ASCII armored OpenPGP key
   34.75 +//      size (in)                   amount of data to handle
   34.76 +//      private_keys (out)          list of identities containing the 
   34.77 +//                                  private keys that have been imported
   34.78  //
   34.79  //  return value:
   34.80  //      PEP_STATUS_OK = 0       key was successfully imported
   34.81 @@ -902,9 +931,47 @@
   34.82          PEP_SESSION session,
   34.83          const char *key_data,
   34.84          size_t size,
   34.85 -        identity_list **private_keys
   34.86 +        identity_list **private_keys       
   34.87      );
   34.88  
   34.89 +// _import_key_with_fpr_return() - 
   34.90 +//                INTERNAL FUNCTION - import keys from data, return optional list 
   34.91 +//                of fprs imported
   34.92 +//
   34.93 +//  parameters:
   34.94 +//      session (in)                session handle
   34.95 +//      key_data (in)               key data, i.e. ASCII armored OpenPGP key
   34.96 +//      size (in)                   amount of data to handle
   34.97 +//      private_keys (out)          list of identities containing the 
   34.98 +//                                  private keys that have been imported
   34.99 +//      imported_keys (out)         if non-NULL, list of actual keys imported
  34.100 +//      changed_public_keys (out)   if non-NULL AND imported_keys is non-NULL:
  34.101 +//                                  bitvector - corresponds to the first 64 keys
  34.102 +//                                  imported. If nth bit is set, import changed a
  34.103 +//                                  key corresponding to the nth element in
  34.104 +//                                  imported keys (i.e. key was in DB and was
  34.105 +//                                  changed by import)
  34.106 +//
  34.107 +//  return value:
  34.108 +//      PEP_STATUS_OK = 0       key was successfully imported
  34.109 +//      PEP_OUT_OF_MEMORY       out of memory
  34.110 +//      PEP_ILLEGAL_VALUE       there is no key data to import, or imported keys was NULL and 
  34.111 +//                              changed_public_keys was not
  34.112 +//
  34.113 +//  caveat:
  34.114 +//      private_keys and imported_keys goes to the ownership of the caller
  34.115 +//      private_keys and imported_keys can be left NULL, it is then ignored
  34.116 +//      *** THIS IS THE ACTUAL FUNCTION IMPLEMENTED BY CRYPTOTECH "import_key" ***
  34.117 +
  34.118 +PEP_STATUS _import_key_with_fpr_return(
  34.119 +        PEP_SESSION session,
  34.120 +        const char *key_data,
  34.121 +        size_t size,
  34.122 +        identity_list** private_keys,
  34.123 +        stringlist_t** imported_keys,
  34.124 +        uint64_t* changed_public_keys // use as bit field for the first 64 changed keys
  34.125 +);
  34.126 +
  34.127  
  34.128  // export_key() - export ascii armored key
  34.129  //
  34.130 @@ -1011,6 +1078,24 @@
  34.131  DYNAMIC_API void pEp_free(void *p);
  34.132  
  34.133  
  34.134 +// pEp_realloc() - reallocate memory allocated by pEp engine
  34.135 +//
  34.136 +//  parameters:
  34.137 +//      p (in)                  pointer to free
  34.138 +//      size (in)               new memory size
  34.139 +//
  34.140 +//  returns:
  34.141 +//      pointer to allocated memory
  34.142 +//
  34.143 +//  The reason for this function is that heap management can be a pretty
  34.144 +//  complex task with Windoze. This realloc() version calls the realloc()
  34.145 +//  implementation of the C runtime library which was used to build pEp engine,
  34.146 +//  so you're using the correct heap. For more information, see:
  34.147 +//  <http://msdn.microsoft.com/en-us/library/windows/desktop/aa366711(v=vs.85).aspx>
  34.148 +
  34.149 +DYNAMIC_API void *pEp_realloc(void *p, size_t size);
  34.150 +
  34.151 +
  34.152  // get_trust() - get the trust level a key has for a person
  34.153  //
  34.154  //  parameters:
  34.155 @@ -1321,6 +1406,79 @@
  34.156  
  34.157  DYNAMIC_API const char *per_machine_directory(void);
  34.158  
  34.159 +// FIXME: replace in canonical style
  34.160 +//
  34.161 +// config_passphrase() - configure a key passphrase for the current session.
  34.162 +//
  34.163 +// A passphrase can be configured into a p≡p session. Then it is used whenever a
  34.164 +// secret key is used which requires a passphrase.
  34.165 +// 
  34.166 +// A passphrase is a string between 1 and 1024 bytes and is only ever present in
  34.167 +// memory. Because strings in the p≡p engine are UTF-8 NFC, the string is
  34.168 +// restricted to 250 code points in UI.
  34.169 +// 
  34.170 +// This function copies the passphrase into the session. It may return
  34.171 +// PEP_OUT_OF_MEMORY. The behaviour of all functions which use secret keys may
  34.172 +// change after this is configured.  Error behaviour
  34.173 +// 
  34.174 +// For any function which may trigger the use of a secret key, if an attempt
  34.175 +// to use a secret key which requires a passphrase occurs and no passphrase
  34.176 +// is configured for the current session, PEP_PASSPHRASE_REQUIRED is
  34.177 +// returned by this function (and thus, all functions which could trigger
  34.178 +// such a usage must be prepared to return this value).  For any function
  34.179 +// which may trigger the use of a secret key, if a passphrase is configured
  34.180 +// and the configured passphrase is the wrong passphrase for the use of a
  34.181 +// given passphrase-protected secret key, PEP_WRONG_PASSPHRASE is returned
  34.182 +// by this function (and thus, all functions which could trigger such a
  34.183 +// usage must be prepared to return this value).
  34.184 +
  34.185 +DYNAMIC_API PEP_STATUS config_passphrase(PEP_SESSION session, const char *passphrase);
  34.186 +
  34.187 +// FIXME: replace in canonical style
  34.188 +//
  34.189 +// Passphrase enablement for newly-generated secret keys
  34.190 +// 
  34.191 +// If it is desired that new p≡p keys are passphrase-protected, the following
  34.192 +// API call is used to enable the addition of passphrases to new keys during key
  34.193 +// generation.
  34.194 +//
  34.195 +// If enabled and a passphrase for new keys has been configured
  34.196 +// through this function (NOT the one above - this is a separate passphrase!),
  34.197 +// then anytime a secret key is generated while enabled, the configured
  34.198 +// passphrase will be used as the passphrase for any newly-generated secret key.
  34.199 +//
  34.200 +// If enabled and a passphrase for new keys has not been configured, then any
  34.201 +// function which can attempt to generate a secret key will return
  34.202 +// PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED.  
  34.203 +//
  34.204 +// If disabled (i.e. not enabled) and a passphrase for new keys has been
  34.205 +// configured, no passphrases will be used for newly-generated keys.
  34.206 +//
  34.207 +// This function copies the passphrase for new keys into a special field that is
  34.208 +// specifically for key generation into the session. It may return
  34.209 +// PEP_OUT_OF_MEMORY. The behaviour of all functions which use secret keys may
  34.210 +// change after this is configured.
  34.211 +//
  34.212 +
  34.213 +DYNAMIC_API PEP_STATUS config_passphrase_for_new_keys(PEP_SESSION session, 
  34.214 +                                                bool enable, 
  34.215 +                                                const char *passphrase);
  34.216 +// set_ident_enc_format() - set the default encryption format for this identity
  34.217 +//                          (value only MIGHT be used, and only in the case where the
  34.218 +//                          message enc_format is PEP_enc_auto. It will be used 
  34.219 +//                          opportunistically in the case on a first-come, first-serve 
  34.220 +//                          basis in the order of to_list, cc_list, and bcc_list. We take 
  34.221 +//                          the first set value we come to)
  34.222 +//
  34.223 +//  parameters:
  34.224 +//      session (in)            session handle
  34.225 +//      identity (in)           identity->user_id and identity->address must NOT be NULL
  34.226 +//      format (in)             the desired default encryption format
  34.227 +//
  34.228 +DYNAMIC_API PEP_STATUS set_ident_enc_format(PEP_SESSION session,
  34.229 +                                            pEp_identity *identity,
  34.230 +                                            PEP_enc_format format);
  34.231 +
  34.232  
  34.233  PEP_STATUS _generate_keypair(PEP_SESSION session, 
  34.234                               pEp_identity *identity,
  34.235 @@ -1392,7 +1550,7 @@
  34.236  PEP_STATUS set_pgp_keypair(PEP_SESSION session, const char* fpr);
  34.237  
  34.238  PEP_STATUS set_pEp_version(PEP_SESSION session, pEp_identity* ident, unsigned int new_ver_major, unsigned int new_ver_minor);
  34.239 -
  34.240 +                
  34.241  PEP_STATUS clear_trust_info(PEP_SESSION session,
  34.242                              const char* user_id,
  34.243                              const char* fpr);
  34.244 @@ -1442,6 +1600,7 @@
  34.245  
  34.246  PEP_STATUS has_partner_contacted_address(PEP_SESSION session, const char* partner_id,
  34.247                                           const char* own_address, bool* was_contacted);
  34.248 +                                                                                  
  34.249  #ifdef __cplusplus
  34.250  }
  34.251  #endif
    35.1 --- a/src/pEp_internal.h	Mon Apr 13 13:08:13 2020 +0200
    35.2 +++ b/src/pEp_internal.h	Tue Jul 07 11:53:12 2020 +0200
    35.3 @@ -1,8 +1,6 @@
    35.4  // This file is under GNU General Public License 3.0
    35.5  // see LICENSE.txt
    35.6  
    35.7 -#define PEP_ENGINE_VERSION "1.1.1"
    35.8 -
    35.9  // maximum attachment size to import as key 1MB, maximum of 20 attachments
   35.10  
   35.11  #define MAX_KEY_SIZE (1024 * 1024)
   35.12 @@ -143,7 +141,11 @@
   35.13  
   35.14      PEP_cryptotech_t *cryptotech;
   35.15      PEP_CIPHER_SUITE cipher_suite;
   35.16 -
   35.17 +    
   35.18 +    char* curr_passphrase;
   35.19 +    bool new_key_pass_enable;
   35.20 +    char* generation_passphrase;
   35.21 +    
   35.22      PEP_transport_t *transports;
   35.23  
   35.24      sqlite3 *db;
   35.25 @@ -162,7 +164,8 @@
   35.26      sqlite3_stmt *get_main_user_fpr;
   35.27      sqlite3_stmt *refresh_userid_default_key;
   35.28      sqlite3_stmt *delete_key;
   35.29 -    sqlite3_stmt *remove_fpr_as_default;
   35.30 +    sqlite3_stmt *remove_fpr_as_identity_default;
   35.31 +    sqlite3_stmt *remove_fpr_as_user_default;
   35.32      sqlite3_stmt *set_person;
   35.33      sqlite3_stmt *update_person;
   35.34      sqlite3_stmt *delete_person;
   35.35 @@ -185,6 +188,7 @@
   35.36      sqlite3_stmt *exists_identity_entry;        
   35.37      sqlite3_stmt *set_identity_flags;
   35.38      sqlite3_stmt *unset_identity_flags;
   35.39 +    sqlite3_stmt *set_ident_enc_format;
   35.40      sqlite3_stmt *set_pEp_version; 
   35.41      sqlite3_stmt *clear_trust_info;   
   35.42      sqlite3_stmt *set_trust;
    36.1 --- a/src/pgp_gpg.h	Mon Apr 13 13:08:13 2020 +0200
    36.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.3 @@ -1,305 +0,0 @@
    36.4 -// This file is under GNU General Public License 3.0
    36.5 -// see LICENSE.txt
    36.6 -
    36.7 -#pragma once
    36.8 -
    36.9 -#include "pEpEngine.h"
   36.10 -
   36.11 -
   36.12 -// pgp_init() - initialize PGP backend
   36.13 -//
   36.14 -//  parameters:
   36.15 -//      session (in)        session handle
   36.16 -//      in_first (in)       true if this is the first session
   36.17 -//
   36.18 -//  return value:
   36.19 -//      PEP_STATUS_OK if PGP backend was successfully initialized
   36.20 -//      or any other value on error
   36.21 -
   36.22 -PEP_STATUS pgp_init(PEP_SESSION session, bool in_first);
   36.23 -
   36.24 -
   36.25 -// pgp_release() - release PGP backend
   36.26 -//
   36.27 -//  paramters:
   36.28 -//      session (in)        session handle
   36.29 -//      out_last (in)       true if this is the last session to release
   36.30 -
   36.31 -void pgp_release(PEP_SESSION session, bool out_last);
   36.32 -
   36.33 -
   36.34 -// pgp_decrypt_and_verify() - decrypt and verify ciphertext
   36.35 -//
   36.36 -//  parameters:
   36.37 -//      session (in)        session handle
   36.38 -//      ctext (in)          bytes with ciphertext
   36.39 -//      csize (in)          size of ciphertext in bytes
   36.40 -//      dsigtext (in)       pointer to bytes with detached signature
   36.41 -//                          or NULL if no detached signature
   36.42 -//      dsigsize (in)       size of detached signature in bytes
   36.43 -//      ptext (out)         bytes with ciphertext
   36.44 -//      psize (out)         size of ciphertext in bytes
   36.45 -//      keylist (out)       list of keys being used; first is the key being
   36.46 -//                          used for signing
   36.47 -//	filename (out)	    PGP filename, when rendered (Optional, only necessary for some PGP implementations (e.g. Symantec),
   36.48 -//                          *** Mostly internal ***
   36.49 -//  return value:
   36.50 -//      PEP_DECRYPTED_AND_VERIFIED      data could be decryped and verified
   36.51 -//      PEP_DECRYPT_SIGNATURE_DOES_NOT_MATCH
   36.52 -//                                      a signature does not match
   36.53 -//      PEP_DECRYPTED                   data could be decrypted but not verified
   36.54 -//      PEP_VERIFIED_AND_TRUSTED        data was unencrypted but perfectly signed
   36.55 -//      PEP_VERIFIED                    data was unencrypted, signature matches
   36.56 -//      PEP_DECRYPT_NO_KEY              data could not be decrypted because a
   36.57 -//                                      key is missing
   36.58 -//      PEP_DECRYPT_WRONG_FORMAT        data format not readable
   36.59 -//      PEP_ILLEGAL_VALUE               parameters wrong
   36.60 -//      PEP_OUT_OF_MEMORY               out of memory error
   36.61 -//      PEP_UNKOWN_ERROR                internal error
   36.62 -
   36.63 -PEP_STATUS pgp_decrypt_and_verify(
   36.64 -        PEP_SESSION session,
   36.65 -        const char *ctext,
   36.66 -        size_t csize,
   36.67 -        const char *dsigtext,
   36.68 -        size_t dsigsize,
   36.69 -        char **ptext,
   36.70 -        size_t *psize,
   36.71 -        stringlist_t **keylist,
   36.72 -        char** filename_ptr
   36.73 -    );
   36.74 -
   36.75 -
   36.76 -// pgp_encrypt_and_sign() - encrypt plaintext and sign
   36.77 -//
   36.78 -//  parameters:
   36.79 -//      session (in)        session handle
   36.80 -//      keylist (in)        first key to sign and encrypt, all other keys to
   36.81 -//                          encrypt
   36.82 -//      ptext (in)          bytes with plaintext
   36.83 -//      psize (in)          size of plaintext in bytes
   36.84 -//      ctext (out)         bytes with ciphertext, ASCII armored
   36.85 -//      csize (out)         size of ciphertext in bytes
   36.86 -//
   36.87 -//  return value:
   36.88 -//      PEP_STATUS_OK                   successful
   36.89 -//      PEP_KEY_NOT_FOUND               key not in keyring
   36.90 -//      PEP_KEY_HAS_AMBIG_NAME          multiple keys match data in keylist
   36.91 -//      PEP_GET_KEY_FAILED              access to keyring failed
   36.92 -//      PEP_ILLEGAL_VALUE               parameters wrong
   36.93 -//      PEP_OUT_OF_MEMORY               out of memory error
   36.94 -//      PEP_UNKOWN_ERROR                internal error
   36.95 -
   36.96 -PEP_STATUS pgp_encrypt_and_sign(
   36.97 -        PEP_SESSION session,
   36.98 -        const stringlist_t *keylist,
   36.99 -        const char *ptext,
  36.100 -        size_t psize,
  36.101 -        char **ctext,
  36.102 -        size_t *csize
  36.103 -    );
  36.104 -
  36.105 -PEP_STATUS pgp_sign_only(
  36.106 -        PEP_SESSION session, const char* fpr, const char *ptext,
  36.107 -        size_t psize, char **stext, size_t *ssize
  36.108 -    );
  36.109 -
  36.110 -// pgp_encrypt_only() - encrypt plaintext
  36.111 -//
  36.112 -//  parameters:
  36.113 -//      session (in)        session handle
  36.114 -//      keylist (in)        keys to encrypt plaintext
  36.115 -//      ptext (in)          bytes with plaintext
  36.116 -//      psize (in)          size of plaintext in bytes
  36.117 -//      ctext (out)         bytes with ciphertext, ASCII armored
  36.118 -//      csize (out)         size of ciphertext in bytes
  36.119 -//
  36.120 -//  return value:
  36.121 -//      PEP_STATUS_OK                   successful
  36.122 -//      PEP_KEY_NOT_FOUND               key not in keyring
  36.123 -//      PEP_KEY_HAS_AMBIG_NAME          multiple keys match data in keylist
  36.124 -//      PEP_GET_KEY_FAILED              access to keyring failed
  36.125 -//      PEP_ILLEGAL_VALUE               parameters wrong
  36.126 -//      PEP_OUT_OF_MEMORY               out of memory error
  36.127 -//      PEP_UNKNOWN_ERROR                internal error
  36.128 -
  36.129 -PEP_STATUS pgp_encrypt_only(
  36.130 -        PEP_SESSION session,
  36.131 -        const stringlist_t *keylist,
  36.132 -        const char *ptext,
  36.133 -        size_t psize,
  36.134 -        char **ctext,
  36.135 -        size_t *csize
  36.136 -    );
  36.137 -
  36.138 -
  36.139 -// pgp_verify_text() - verify signed data
  36.140 -//
  36.141 -//  parameters:
  36.142 -//      session (in)        session handle
  36.143 -//      keylist (in)        keys to encrypt plaintext
  36.144 -//      text (in)           data to verify, may include signature
  36.145 -//      size (in)           size of data to verify in bytes
  36.146 -//      signature (in)      detached signature data or NULL
  36.147 -//      sig_size (in)       size of detached signature in bytes
  36.148 -//      keylist (out)       list of keys being used for signing
  36.149 -//
  36.150 -//  return value:
  36.151 -//      PEP_VERIFIED_AND_TRUSTED        data was unencrypted but perfectly signed
  36.152 -//                                      this is depending on PGP trust concept
  36.153 -//      PEP_VERIFIED                    data was unencrypted, signature matches
  36.154 -//      PEP_DECRYPT_NO_KEY              data could not be verified because a
  36.155 -//                                      key is missing
  36.156 -//      PEP_DECRYPT_WRONG_FORMAT        data format not readable
  36.157 -//      PEP_ILLEGAL_VALUE               parameters wrong
  36.158 -//      PEP_OUT_OF_MEMORY               out of memory error
  36.159 -//      PEP_UNKOWN_ERROR                internal error
  36.160 -
  36.161 -PEP_STATUS pgp_verify_text(
  36.162 -        PEP_SESSION session,
  36.163 -        const char *text,
  36.164 -        size_t size,
  36.165 -        const char *signature,
  36.166 -        size_t sig_size,
  36.167 -        stringlist_t **keylist
  36.168 -    );
  36.169 -
  36.170 -
  36.171 -// pgp_delete_keypair() - delete key or keypair
  36.172 -//
  36.173 -//  parameters:
  36.174 -//      session (in)        session handle
  36.175 -//      fpr (in)            fingerprint of key or keypair to delete
  36.176 -
  36.177 -PEP_STATUS pgp_delete_keypair(PEP_SESSION session, const char *fpr);
  36.178 -
  36.179 -
  36.180 -// pgp_export_keydata() - export public key data ASCII armored
  36.181 -//
  36.182 -//  parameters:
  36.183 -//      session (in)        session handle
  36.184 -//      fpr (in)            fingerprint of public key to export
  36.185 -//      key_data (out)      ascii armored key data
  36.186 -//      size (out)          size of ascii armored key data
  36.187 -//      secret (in)         additionally export private key data
  36.188 -
  36.189 -PEP_STATUS pgp_export_keydata(
  36.190 -        PEP_SESSION session,
  36.191 -        const char *fpr,
  36.192 -        char **key_data,
  36.193 -        size_t *size,
  36.194 -        bool secret
  36.195 -    );
  36.196 -
  36.197 -
  36.198 -// pgp_find_keys() - find keys where fprs are matching a pattern
  36.199 -//
  36.200 -//  parameters:
  36.201 -//      session (in)        session handle
  36.202 -//      pattern (in)        UTF-8 string with pattern
  36.203 -//      keylist (out)       list of fprs matching
  36.204 -
  36.205 -PEP_STATUS pgp_find_keys(
  36.206 -        PEP_SESSION session,
  36.207 -        const char *pattern,
  36.208 -        stringlist_t **keylist
  36.209 -    );
  36.210 -
  36.211 -
  36.212 -PEP_STATUS pgp_list_keyinfo(
  36.213 -        PEP_SESSION session,
  36.214 -        const char* pattern,
  36.215 -        stringpair_list_t** keyinfo_list
  36.216 -    );
  36.217 -
  36.218 -PEP_STATUS pgp_generate_keypair(
  36.219 -        PEP_SESSION session,
  36.220 -        pEp_identity *identity
  36.221 -    );
  36.222 -
  36.223 -PEP_STATUS pgp_get_key_rating(
  36.224 -        PEP_SESSION session,
  36.225 -        const char *fpr,
  36.226 -        PEP_comm_type *comm_type
  36.227 -    );
  36.228 -
  36.229 -PEP_STATUS pgp_import_keydata(
  36.230 -        PEP_SESSION session,
  36.231 -        const char *key_data,
  36.232 -        size_t size,
  36.233 -        identity_list **private_idents
  36.234 -    );
  36.235 -
  36.236 -PEP_STATUS pgp_import_private_keydata(
  36.237 -        PEP_SESSION session,
  36.238 -        const char *key_data,
  36.239 -        size_t size,
  36.240 -        identity_list **private_idents
  36.241 -    );
  36.242 -
  36.243 -PEP_STATUS pgp_recv_key(PEP_SESSION session, const char *pattern);
  36.244 -
  36.245 -PEP_STATUS pgp_send_key(PEP_SESSION session, const char *pattern);
  36.246 -
  36.247 -PEP_STATUS pgp_renew_key(
  36.248 -        PEP_SESSION session,
  36.249 -        const char *fpr,
  36.250 -        const timestamp *ts
  36.251 -    );
  36.252 -
  36.253 -PEP_STATUS pgp_revoke_key(
  36.254 -        PEP_SESSION session,
  36.255 -        const char *fpr,
  36.256 -        const char *reason
  36.257 -    );
  36.258 -
  36.259 -PEP_STATUS pgp_key_expired(
  36.260 -        PEP_SESSION session,
  36.261 -        const char *fpr,
  36.262 -        const time_t when,
  36.263 -        bool *expired
  36.264 -    );
  36.265 -
  36.266 -PEP_STATUS pgp_key_revoked(
  36.267 -        PEP_SESSION session,
  36.268 -        const char *fpr,
  36.269 -        bool *revoked
  36.270 -    );
  36.271 -
  36.272 -PEP_STATUS pgp_key_created(
  36.273 -        PEP_SESSION session,
  36.274 -        const char *fpr,
  36.275 -        time_t *created
  36.276 -    );
  36.277 -
  36.278 -PEP_STATUS pgp_contains_priv_key(
  36.279 -        PEP_SESSION session, 
  36.280 -        const char *fpr,
  36.281 -        bool *has_private
  36.282 -    );
  36.283 -
  36.284 -PEP_STATUS pgp_find_private_keys(
  36.285 -        PEP_SESSION session,
  36.286 -        const char *pattern,
  36.287 -        stringlist_t **keylist
  36.288 -    );
  36.289 -
  36.290 -PEP_STATUS pgp_binary(const char **path);
  36.291 -
  36.292 -// Returns first failure status, if there were any. Keys may have been
  36.293 -// imported into DB regardless of status.
  36.294 -
  36.295 -PEP_STATUS pgp_import_ultimately_trusted_keypairs(PEP_SESSION session);
  36.296 -
  36.297 -/* Really only internal. */
  36.298 -PEP_STATUS pgp_replace_only_uid(
  36.299 -        PEP_SESSION session,
  36.300 -        const char* fpr,
  36.301 -        const char* realname,
  36.302 -        const char* email
  36.303 -    );
  36.304 -
  36.305 -PEP_STATUS pgp_config_cipher_suite(PEP_SESSION session,
  36.306 -        PEP_CIPHER_SUITE suite);
  36.307 -
  36.308 -#define PGP_BINARY_PATH pgp_binary
    37.1 --- a/src/pgp_sequoia.c	Mon Apr 13 13:08:13 2020 +0200
    37.2 +++ b/src/pgp_sequoia.c	Tue Jul 07 11:53:12 2020 +0200
    37.3 @@ -361,6 +361,7 @@
    37.4                                   "CREATE INDEX IF NOT EXISTS userids_index\n"
    37.5                                   "  ON userids (userid COLLATE EMAIL, primary_key)\n",
    37.6                                   NULL, NULL, NULL);
    37.7 +
    37.8      if (sqlite_result != SQLITE_OK)
    37.9          ERROR_OUT(NULL, PEP_INIT_CANNOT_OPEN_DB,
   37.10                    "creating userids table: %s",
   37.11 @@ -482,6 +483,7 @@
   37.12                               -1, &session->sq_sql.delete_keypair, NULL);
   37.13      assert(sqlite_result == SQLITE_OK);
   37.14  
   37.15 +    
   37.16      session->policy = pgp_null_policy ();
   37.17      if (! session->policy)
   37.18          ERROR_OUT(NULL, PEP_OUT_OF_MEMORY,
   37.19 @@ -760,14 +762,53 @@
   37.20      return status;
   37.21  }
   37.22  
   37.23 +// end detect possibly changed key stuff
   37.24 +static PEP_STATUS serialize_cert(PEP_SESSION session, pgp_cert_t cert,
   37.25 +                                 void** buffer_ptr, size_t* buffer_size_ptr)   {
   37.26 +    
   37.27 +    if (!session || !cert || !buffer_ptr || !buffer_size_ptr)
   37.28 +        return PEP_ILLEGAL_VALUE;
   37.29 +        
   37.30 +    PEP_STATUS status = PEP_STATUS_OK;
   37.31 +        
   37.32 +    void* curr_buffer = NULL;
   37.33 +    size_t curr_buffer_len = 0;                                 
   37.34 +    pgp_status_t pgp_status;
   37.35 +    pgp_tsk_t tsk = NULL;
   37.36 +    pgp_error_t err = NULL;
   37.37 +    
   37.38 +    pgp_writer_t writer = pgp_writer_alloc(&curr_buffer, &curr_buffer_len);
   37.39 +    if (!writer)
   37.40 +        ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
   37.41 +
   37.42 +    tsk = pgp_cert_as_tsk(cert);
   37.43 +    pgp_status = pgp_tsk_serialize(&err, tsk, writer);
   37.44 +    if (pgp_status != 0)
   37.45 +        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Serializing certificates");
   37.46 +    
   37.47 +out: 
   37.48 +    pgp_tsk_free(tsk);
   37.49 +    pgp_writer_free(writer);   
   37.50 +
   37.51 +    if (status == PEP_STATUS_OK) {
   37.52 +        *buffer_ptr = curr_buffer;
   37.53 +        *buffer_size_ptr = curr_buffer_len;
   37.54 +    }
   37.55 +    else
   37.56 +        free(buffer_ptr);
   37.57 +        
   37.58 +    T(" -> %s", pEp_status_to_string(status));
   37.59 +    return status;    
   37.60 +}
   37.61 +
   37.62  
   37.63  // Saves the specified certificates.
   37.64  //
   37.65  // This function takes ownership of CERT.
   37.66 -static PEP_STATUS cert_save(PEP_SESSION, pgp_cert_t, identity_list **)
   37.67 +static PEP_STATUS cert_save(PEP_SESSION, pgp_cert_t, identity_list **, bool* changed_ptr)
   37.68      __attribute__((nonnull(1, 2)));
   37.69  static PEP_STATUS cert_save(PEP_SESSION session, pgp_cert_t cert,
   37.70 -                           identity_list **private_idents)
   37.71 +                           identity_list **private_idents, bool* changed_ptr)
   37.72  {
   37.73      PEP_STATUS status = PEP_STATUS_OK;
   37.74      pgp_error_t err = NULL;
   37.75 @@ -775,11 +816,17 @@
   37.76      char *fpr = NULL;
   37.77      void *tsk_buffer = NULL;
   37.78      size_t tsk_buffer_len = 0;
   37.79 +    void *curr_buffer = NULL;
   37.80 +    size_t curr_buffer_len = 0;
   37.81      int tried_commit = 0;
   37.82      pgp_cert_key_iter_t key_iter = NULL;
   37.83 -    pgp_user_id_bundle_iter_t user_id_iter = NULL;
   37.84 +    pgp_cert_valid_user_id_iter_t ua_iter = NULL;
   37.85 +    pgp_valid_user_id_amalgamation_t ua = NULL;
   37.86 +    pgp_packet_t user_id = NULL;
   37.87      char *email = NULL;
   37.88      char *name = NULL;
   37.89 +    
   37.90 +    bool _changed = false;    
   37.91  
   37.92      sqlite3_stmt *stmt = session->sq_sql.begin_transaction;
   37.93      int sqlite_result = sqlite3_step(stmt);
   37.94 @@ -799,29 +846,44 @@
   37.95      if (status == PEP_KEY_NOT_FOUND)
   37.96          status = PEP_STATUS_OK;
   37.97      else
   37.98 -        ERROR_OUT(NULL, status, "Looking up %s", fpr);
   37.99 +        ERROR_OUT(NULL, status, "Looking up %s", fpr);    
  37.100 +    
  37.101      if (current) {
  37.102 +        if (changed_ptr) {
  37.103 +            // Serialize current for comparison (ugh).        
  37.104 +            status = serialize_cert(session, current, &curr_buffer, &curr_buffer_len);
  37.105 +            if (status != PEP_STATUS_OK)
  37.106 +                ERROR_OUT(NULL, status, "Could not serialize existing cert for change check");
  37.107 +        }        
  37.108 +
  37.109          cert = pgp_cert_merge(&err, cert, current);
  37.110          if (! cert)
  37.111              ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Merging certificates");
  37.112      }
  37.113 +    else if (changed_ptr)
  37.114 +        _changed = true;
  37.115  
  37.116      int is_tsk = pgp_cert_is_tsk(cert);
  37.117  
  37.118      // Serialize it.
  37.119 -    pgp_writer_t writer = pgp_writer_alloc(&tsk_buffer, &tsk_buffer_len);
  37.120 -    if (! writer)
  37.121 -        ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "out of memory");
  37.122 -
  37.123 -    pgp_status_t pgp_status;
  37.124 -    pgp_tsk_t tsk = pgp_cert_as_tsk(cert);
  37.125 -    pgp_status = pgp_tsk_serialize(&err, tsk, writer);
  37.126 -    pgp_tsk_free(tsk);
  37.127 -    pgp_writer_free(writer);
  37.128 -    if (pgp_status != 0)
  37.129 -        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Serializing certificates");
  37.130 -
  37.131 -
  37.132 +    // NOTE: Just because it's called tsk in tsk_buffer does NOT mean it necessarily 
  37.133 +    //       has secret key material; it is just that is could. is_tsk is the 
  37.134 +    //       part that asks whether or not it contains such.
  37.135 +    status = serialize_cert(session, cert, &tsk_buffer, &tsk_buffer_len);
  37.136 +    if (status != PEP_STATUS_OK)
  37.137 +        ERROR_OUT(NULL, status, "Could not serialize tsk cert for saving");
  37.138 +    
  37.139 +    // Before we do anything else, if we need to know if things MAY have changed, 
  37.140 +    // we check the key blob (this is not comprehensive and can generate false 
  37.141 +    // positives)
  37.142 +    //
  37.143 +    if (changed_ptr) {
  37.144 +        if (!current || !curr_buffer || (curr_buffer_len != tsk_buffer_len))
  37.145 +            _changed = true;
  37.146 +        else if (memcmp(curr_buffer, tsk_buffer, tsk_buffer_len) != 0)
  37.147 +            _changed = true;
  37.148 +    }
  37.149 +                    
  37.150      // Insert the TSK into the DB.
  37.151      stmt = session->sq_sql.cert_save_insert_primary;
  37.152      sqlite3_bind_text(stmt, 1, fpr, -1, SQLITE_STATIC);
  37.153 @@ -866,18 +928,17 @@
  37.154  
  37.155      // Insert the "userids".
  37.156      stmt = session->sq_sql.cert_save_insert_userids;
  37.157 -    user_id_iter = pgp_cert_user_id_bundle_iter(cert);
  37.158 -    pgp_user_id_bundle_t bundle;
  37.159 +    ua_iter = pgp_cert_valid_user_id_iter(cert, session->policy, 0);
  37.160      int first = 1;
  37.161 -    while ((bundle = pgp_user_id_bundle_iter_next(user_id_iter))) {
  37.162 -        char *user_id_value = pgp_user_id_bundle_user_id(bundle);
  37.163 -        if (!user_id_value || !*user_id_value)
  37.164 -            continue;
  37.165 -
  37.166 -        // Ignore user ids with a self-revocation certificate, but no
  37.167 -        // self-signature.
  37.168 -        if (!pgp_user_id_bundle_selfsig(bundle, session->policy)) {
  37.169 -            free(user_id_value);
  37.170 +    while ((ua = pgp_cert_valid_user_id_iter_next(ua_iter))) {
  37.171 +        user_id = pgp_valid_user_id_amalgamation_user_id(ua);
  37.172 +
  37.173 +        const uint8_t *user_id_value = pgp_user_id_value(user_id, NULL);
  37.174 +        if (!user_id_value || !*user_id_value) {
  37.175 +            pgp_packet_free (user_id);
  37.176 +            user_id = NULL;
  37.177 +            pgp_valid_user_id_amalgamation_free(ua);
  37.178 +            ua = NULL;
  37.179              continue;
  37.180          }
  37.181  
  37.182 @@ -886,16 +947,13 @@
  37.183          free(email);
  37.184          email = NULL;
  37.185  
  37.186 -        pgp_packet_t userid = pgp_user_id_new (user_id_value);
  37.187 -        pgp_user_id_name(NULL, userid, &name);
  37.188 +        pgp_user_id_name(NULL, user_id, &name);
  37.189          // Try to get the normalized address.
  37.190 -        pgp_user_id_email_normalized(NULL, userid, &email);
  37.191 +        pgp_user_id_email_normalized(NULL, user_id, &email);
  37.192          if (! email)
  37.193              // Ok, it's not a proper RFC 2822 name-addr.  Perhaps it
  37.194              // is a URI.
  37.195 -            pgp_user_id_uri(NULL, userid, &email);
  37.196 -        pgp_packet_free(userid);
  37.197 -        free(user_id_value);
  37.198 +            pgp_user_id_uri(NULL, user_id, &email);
  37.199  
  37.200          if (email) {
  37.201              T("  userid: %s", email);
  37.202 @@ -907,7 +965,6 @@
  37.203              sqlite3_reset(stmt);
  37.204  
  37.205              if (sqlite_result != SQLITE_DONE) {
  37.206 -                pgp_user_id_bundle_iter_free(user_id_iter);
  37.207                  ERROR_OUT(NULL, PEP_UNKNOWN_ERROR,
  37.208                            "Updating userids: %s", sqlite3_errmsg(session->key_db));
  37.209              }
  37.210 @@ -926,9 +983,11 @@
  37.211                  ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "identity_list_add");
  37.212          }
  37.213  
  37.214 +        pgp_packet_free (user_id);
  37.215 +        user_id = NULL;
  37.216 +        pgp_valid_user_id_amalgamation_free(ua);
  37.217 +        ua = NULL;
  37.218      }
  37.219 -    pgp_user_id_bundle_iter_free(user_id_iter);
  37.220 -    user_id_iter = NULL;
  37.221  
  37.222   out:
  37.223      // Prevent ERROR_OUT from causing an infinite loop.
  37.224 @@ -948,13 +1007,19 @@
  37.225  
  37.226      T("(%s) -> %s", fpr, pEp_status_to_string(status));
  37.227  
  37.228 +    if (changed_ptr)
  37.229 +        *changed_ptr = _changed;
  37.230 +
  37.231      free(email);
  37.232      free(name);
  37.233 -    pgp_user_id_bundle_iter_free(user_id_iter);
  37.234 +    pgp_packet_free(user_id);
  37.235 +    pgp_valid_user_id_amalgamation_free(ua);
  37.236 +    pgp_cert_valid_user_id_iter_free(ua_iter);
  37.237      pgp_cert_key_iter_free(key_iter);
  37.238      if (stmt)
  37.239 -      sqlite3_reset(stmt);
  37.240 +        sqlite3_reset(stmt);
  37.241      free(tsk_buffer);
  37.242 +    free(curr_buffer);
  37.243      pgp_cert_free(cert);
  37.244      free(fpr);
  37.245      pgp_fingerprint_free(pgp_fpr);
  37.246 @@ -980,6 +1045,9 @@
  37.247      // Whether we decrypted anything.
  37.248      int decrypted;
  37.249  
  37.250 +    int missing_passphrase;
  37.251 +    int bad_passphrase;
  37.252 +
  37.253      // The filename stored in the literal data packet.  Note: this is
  37.254      // *not* protected by the signature and should not be trusted!!!
  37.255      char *filename;
  37.256 @@ -1032,6 +1100,7 @@
  37.257          // Prevent iterations, which isn't needed since we don't
  37.258          // support SKESKs.
  37.259          return PGP_STATUS_UNKNOWN_ERROR;
  37.260 +        
  37.261      cookie->get_secret_keys_called = 1;
  37.262  
  37.263      T("%zd PKESKs", pkesk_count);
  37.264 @@ -1073,7 +1142,7 @@
  37.265          assert(is_tsk == pgp_cert_is_tsk(cert));
  37.266          if (! is_tsk)
  37.267              goto eol;
  37.268 -
  37.269 +        
  37.270          key_iter = pgp_cert_key_iter(cert);
  37.271          while (key = NULL, (ka = pgp_cert_key_iter_next(key_iter))) {
  37.272              key = pgp_key_amalgamation_key (ka);
  37.273 @@ -1095,9 +1164,33 @@
  37.274              goto eol;
  37.275          }
  37.276  
  37.277 +        if (!pgp_key_has_unencrypted_secret(key)) {
  37.278 +            const char* pass = session->curr_passphrase;
  37.279 +            if (pass && pass[0]) {
  37.280 +                pgp_key_t decrypted_key = NULL;
  37.281 +                decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
  37.282 +                                             strlen(session->curr_passphrase));                             
  37.283 +                if (!decrypted_key) {                               
  37.284 +                    DUMP_ERR(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
  37.285 +                    cookie->bad_passphrase = 1;
  37.286 +                    goto eol;
  37.287 +                }
  37.288 +                else {
  37.289 +                    pgp_key_free(key);
  37.290 +                    key = decrypted_key;
  37.291 +                }
  37.292 +            }
  37.293 +            else {
  37.294 +                DUMP_ERR(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
  37.295 +                cookie->missing_passphrase = 1;
  37.296 +                goto eol;
  37.297 +            }    
  37.298 +        }
  37.299 +
  37.300          uint8_t algo;
  37.301          uint8_t session_key[1024];
  37.302          size_t session_key_len = sizeof(session_key);
  37.303 +
  37.304          if (pgp_pkesk_decrypt(&err, pkesk, key, &algo,
  37.305                                session_key, &session_key_len) != 0) {
  37.306              DUMP_ERR(err, PEP_UNKNOWN_ERROR, "pgp_pkesk_decrypt");
  37.307 @@ -1105,9 +1198,8 @@
  37.308          }
  37.309  
  37.310          sk = pgp_session_key_from_bytes (session_key, session_key_len);
  37.311 -        pgp_status_t status;
  37.312 -        if ((status = decrypt (decrypt_cookie, algo, sk))) {
  37.313 -            DUMP_STATUS(status, PEP_UNKNOWN_ERROR, "decrypt_cb");
  37.314 +        if (! decrypt (decrypt_cookie, algo, sk)) {
  37.315 +            DUMP_STATUS(PGP_STATUS_UNKNOWN_ERROR, PEP_CANNOT_DECRYPT_UNKNOWN, "decrypt_cb");
  37.316              goto eol;
  37.317          }
  37.318  
  37.319 @@ -1151,7 +1243,29 @@
  37.320  
  37.321              while (key = NULL, (ka = pgp_cert_key_iter_next(key_iter))) {
  37.322                  key = pgp_key_amalgamation_key (ka);
  37.323 -
  37.324 +                
  37.325 +                if (!pgp_key_has_unencrypted_secret(key)) {
  37.326 +                    const char* pass = session->curr_passphrase;
  37.327 +                    if (pass && pass[0]) {
  37.328 +                        pgp_key_t decrypted_key = NULL;
  37.329 +                        decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
  37.330 +                                                     strlen(session->curr_passphrase));                             
  37.331 +                        if (!decrypted_key) {                               
  37.332 +                            DUMP_ERR(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
  37.333 +                            cookie->bad_passphrase = 1;
  37.334 +                            continue;
  37.335 +                        }
  37.336 +                        else {
  37.337 +                            pgp_key_free(key);
  37.338 +                            key = decrypted_key;
  37.339 +                        }
  37.340 +                    }
  37.341 +                    else {
  37.342 +                        DUMP_ERR(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
  37.343 +                        cookie->missing_passphrase = 1;
  37.344 +                        continue;
  37.345 +                    }    
  37.346 +                }
  37.347                  // Note: for decryption to appear to succeed, we must
  37.348                  // get a valid algorithm (8 of 256 values) and a
  37.349                  // 16-bit checksum must match.  Thus, we have about a
  37.350 @@ -1178,9 +1292,8 @@
  37.351  
  37.352                  pgp_session_key_t sk = pgp_session_key_from_bytes (session_key,
  37.353                                                                     session_key_len);
  37.354 -                pgp_status_t status;
  37.355 -                if ((status = decrypt (decrypt_cookie, algo, sk))) {
  37.356 -                    DUMP_STATUS(status, PEP_UNKNOWN_ERROR, "decrypt_cb");
  37.357 +                if (! decrypt (decrypt_cookie, algo, sk)) {
  37.358 +                    DUMP_STATUS(PGP_STATUS_UNKNOWN_ERROR, PEP_CANNOT_DECRYPT_UNKNOWN, "decrypt_cb");
  37.359                      goto eol2;
  37.360                  }
  37.361  
  37.362 @@ -1220,7 +1333,7 @@
  37.363      struct decrypt_cookie *cookie = cookie_opaque;
  37.364  
  37.365      pgp_message_structure_iter_t iter
  37.366 -        = pgp_message_structure_iter (structure);
  37.367 +        = pgp_message_structure_into_iter (structure);
  37.368      for (pgp_message_layer_t layer = pgp_message_structure_iter_next (iter);
  37.369           layer;
  37.370           layer = pgp_message_structure_iter_next (iter)) {
  37.371 @@ -1354,7 +1467,7 @@
  37.372                          cookie->revoked_key ++;
  37.373                      } else {
  37.374                          pgp_revocation_status_free (rs);
  37.375 -                        rs = pgp_cert_revoked (cert, cookie->session->policy, 0);
  37.376 +                        rs = pgp_cert_revocation_status (cert, cookie->session->policy, 0);
  37.377                          if (pgp_revocation_status_variant(rs)
  37.378                              == PGP_REVOCATION_STATUS_REVOKED) {
  37.379                              // Cert is revoked.
  37.380 @@ -1428,7 +1541,6 @@
  37.381      }
  37.382  
  37.383      pgp_message_structure_iter_free (iter);
  37.384 -    pgp_message_structure_free (structure);
  37.385  
  37.386      return PGP_STATUS_SUCCESS;
  37.387  }
  37.388 @@ -1463,7 +1575,7 @@
  37.389      char** filename_ptr)
  37.390  {
  37.391      PEP_STATUS status = PEP_STATUS_OK;
  37.392 -    struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  37.393 +    struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL };
  37.394      pgp_reader_t reader = NULL;
  37.395      pgp_writer_t writer = NULL;
  37.396      pgp_reader_t decryptor = NULL;
  37.397 @@ -1495,9 +1607,16 @@
  37.398                                    get_public_keys_cb, decrypt_cb,
  37.399                                    check_signatures_cb, inspect_cb,
  37.400                                    &cookie, 0);
  37.401 -    if (! decryptor)
  37.402 -        ERROR_OUT(err, PEP_DECRYPT_NO_KEY, "pgp_decryptor_new");
  37.403 -
  37.404 +    if (! decryptor) {
  37.405 +        if (cookie.bad_passphrase)
  37.406 +            status = PEP_WRONG_PASSPHRASE;
  37.407 +        else if (cookie.missing_passphrase)
  37.408 +            status = PEP_PASSPHRASE_REQUIRED;
  37.409 +        else 
  37.410 +            status = PEP_DECRYPT_NO_KEY;
  37.411 +        ERROR_OUT(err, status, "pgp_decryptor_new");
  37.412 +    }
  37.413 +    
  37.414      // Copy 128 MB at a time.
  37.415      ssize_t nread;
  37.416      while ((nread = pgp_reader_copy (&err, decryptor, writer,
  37.417 @@ -1578,7 +1697,6 @@
  37.418      struct decrypt_cookie cookie = { session, 0, NULL, NULL, 0, 0, 0, };
  37.419      pgp_reader_t reader = NULL;
  37.420      pgp_reader_t dsig_reader = NULL;
  37.421 -    pgp_reader_t verifier = NULL;
  37.422  
  37.423      if (size == 0 || sig_size == 0)
  37.424          return PEP_DECRYPT_WRONG_FORMAT;
  37.425 @@ -1629,21 +1747,36 @@
  37.426              ERROR_OUT(NULL, PEP_OUT_OF_MEMORY, "Creating signature reader");
  37.427      }
  37.428  
  37.429 -    if (dsig_reader)
  37.430 -        verifier = pgp_detached_verifier_new(&err, session->policy,
  37.431 -                                             dsig_reader, reader,
  37.432 -                                             get_public_keys_cb,
  37.433 -                                             check_signatures_cb,
  37.434 -                                             &cookie, 0);
  37.435 -    else
  37.436 +    if (dsig_reader) {
  37.437 +        pgp_detached_verifier_t verifier
  37.438 +            = pgp_detached_verifier_new(&err, session->policy,
  37.439 +                                        dsig_reader,
  37.440 +                                        get_public_keys_cb,
  37.441 +                                        check_signatures_cb,
  37.442 +                                        NULL,
  37.443 +                                        &cookie, 0);
  37.444 +        if (! verifier)
  37.445 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Creating verifier");
  37.446 +
  37.447 +        pgp_status_t pgp_status = pgp_detached_verifier_verify (&err, verifier, reader);
  37.448 +        pgp_detached_verifier_free (verifier);
  37.449 +        if (pgp_status)
  37.450 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Verifying data");
  37.451 +    } else {
  37.452 +        pgp_reader_t verifier = NULL;
  37.453          verifier = pgp_verifier_new(&err, session->policy, reader,
  37.454                                      get_public_keys_cb,
  37.455                                      check_signatures_cb,
  37.456 +                                    NULL,
  37.457                                      &cookie, 0);
  37.458 -    if (! verifier)
  37.459 -        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Creating verifier");
  37.460 -    if (pgp_reader_discard(&err, verifier) < 0)
  37.461 -        ERROR_OUT(err, PEP_UNKNOWN_ERROR, "verifier");
  37.462 +        if (! verifier)
  37.463 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Creating verifier");
  37.464 +
  37.465 +        pgp_status_t pgp_status = pgp_reader_discard(&err, verifier);
  37.466 +        pgp_reader_free(verifier);
  37.467 +        if (pgp_status)
  37.468 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "verifier");
  37.469 +    }
  37.470  
  37.471      if (! cookie.signer_keylist) {
  37.472          cookie.signer_keylist = new_stringlist("");
  37.473 @@ -1689,7 +1822,6 @@
  37.474          free_stringlist(cookie.signer_keylist);
  37.475      }
  37.476  
  37.477 -    pgp_reader_free(verifier);
  37.478      pgp_reader_free(reader);
  37.479      pgp_reader_free(dsig_reader);
  37.480  
  37.481 @@ -1720,6 +1852,9 @@
  37.482      pgp_signer_t signer = NULL;
  37.483      pgp_writer_stack_t ws = NULL;
  37.484  
  37.485 +    bool bad_pass = false;
  37.486 +    bool missing_pass = false;                    
  37.487 +
  37.488      status = cert_find_by_fpr_hex(session, fpr, true, &signer_cert, NULL);
  37.489      ERROR_OUT(NULL, status, "Looking up key '%s'", fpr);
  37.490  
  37.491 @@ -1727,7 +1862,7 @@
  37.492      pgp_cert_valid_key_iter_alive(iter);
  37.493      pgp_cert_valid_key_iter_revoked(iter, false);
  37.494      pgp_cert_valid_key_iter_for_signing (iter);
  37.495 -    pgp_cert_valid_key_iter_unencrypted_secret (iter);
  37.496 +//    pgp_cert_valid_key_iter_unencrypted_secret (iter);
  37.497  
  37.498      // If there are multiple signing capable subkeys, we just take
  37.499      // the first one, whichever one that happens to be.
  37.500 @@ -1738,7 +1873,50 @@
  37.501  
  37.502      // pgp_key_into_key_pair needs to own the key, but here we
  37.503      // only get a reference (which we still need to free).
  37.504 -    pgp_key_t key = pgp_valid_key_amalgamation_key (ka);
  37.505 +    
  37.506 +    pgp_key_t key = NULL;
  37.507 +    for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {                       
  37.508 +        // pgp_key_into_key_pair needs to own the key, but here we
  37.509 +        // only get a reference (which we still need to free).
  37.510 +        key = pgp_valid_key_amalgamation_key (ka);
  37.511 +
  37.512 +        if (pgp_key_has_unencrypted_secret(key)) 
  37.513 +            break;
  37.514 +        else {
  37.515 +            const char* pass = session->curr_passphrase;
  37.516 +            if (pass && pass[0]) {
  37.517 +                pgp_key_t decrypted_key = NULL;
  37.518 +                decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
  37.519 +                                                        strlen(session->curr_passphrase));                             
  37.520 +                pgp_key_free(key);
  37.521 +                key = NULL;
  37.522 +                
  37.523 +                if (!decrypted_key) {                               
  37.524 +                    bad_pass = true;
  37.525 +                    continue;
  37.526 +                }    
  37.527 +                else {
  37.528 +                    key = decrypted_key;
  37.529 +                    break;
  37.530 +                }
  37.531 +            }
  37.532 +            else {
  37.533 +                pgp_key_free(key);
  37.534 +                key = NULL;
  37.535 +                missing_pass = true;
  37.536 +                continue;
  37.537 +            }
  37.538 +        }
  37.539 +    }
  37.540 +    if (!key) {
  37.541 +        if (bad_pass)
  37.542 +            ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
  37.543 +        else if (missing_pass)    
  37.544 +            ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
  37.545 +        else        
  37.546 +            ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");            
  37.547 +    }    
  37.548 +    
  37.549      signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
  37.550      pgp_key_free (key);
  37.551      if (! signing_keypair)
  37.552 @@ -1940,23 +2118,70 @@
  37.553      // pgp_encrypt_new consumes the recipients (but not the keys).
  37.554      recipient_count = 0;
  37.555  
  37.556 -    if (sign) {
  37.557 +    bool bad_pass = false;
  37.558 +    bool missing_pass = false;                
  37.559 +
  37.560 +    if (sign) {            
  37.561 +        
  37.562          iter = pgp_cert_valid_key_iter(signer_cert, session->policy, 0);
  37.563          pgp_cert_valid_key_iter_alive(iter);
  37.564          pgp_cert_valid_key_iter_revoked(iter, false);
  37.565          pgp_cert_valid_key_iter_for_signing (iter);
  37.566 -        pgp_cert_valid_key_iter_unencrypted_secret (iter);
  37.567 -
  37.568 +//        pgp_cert_valid_key_iter_unencrypted_secret (iter);
  37.569 +
  37.570 +        
  37.571          // If there are multiple signing capable subkeys, we just take
  37.572 -        // the first one, whichever one that happens to be.
  37.573 +        // the first one, whichever one that happens to be.            
  37.574 +            
  37.575          ka = pgp_cert_valid_key_iter_next (iter, NULL, NULL);
  37.576          if (! ka)
  37.577              ERROR_OUT (err, PEP_UNKNOWN_ERROR,
  37.578                         "%s has no signing capable key", keylist->value);
  37.579  
  37.580 -        // pgp_key_into_key_pair needs to own the key, but here we
  37.581 -        // only get a reference (which we still need to free).
  37.582 -        pgp_key_t key = pgp_valid_key_amalgamation_key (ka);
  37.583 +        pgp_key_t key = NULL;
  37.584 +        for ( ; ka ; (ka = pgp_cert_valid_key_iter_next(iter, NULL, NULL))) {                       
  37.585 +            // pgp_key_into_key_pair needs to own the key, but here we
  37.586 +            // only get a reference (which we still need to free).
  37.587 +            key = pgp_valid_key_amalgamation_key (ka);
  37.588 +
  37.589 +            if (pgp_key_has_unencrypted_secret(key)) 
  37.590 +                break;
  37.591 +            else {
  37.592 +                const char* pass = session->curr_passphrase;
  37.593 +                if (pass && pass[0]) {
  37.594 +                    pgp_key_t decrypted_key = NULL;
  37.595 +                    decrypted_key = pgp_key_decrypt_secret(&err, pgp_key_clone(key), (uint8_t*)session->curr_passphrase,
  37.596 +                                                            strlen(session->curr_passphrase));                             
  37.597 +                    pgp_key_free(key);
  37.598 +                    key = NULL;
  37.599 +                    
  37.600 +                    if (!decrypted_key) {                               
  37.601 +                        bad_pass = true;
  37.602 +                        continue;
  37.603 +                    }    
  37.604 +                    else {
  37.605 +                        key = decrypted_key;
  37.606 +                        break;
  37.607 +                    }
  37.608 +                }
  37.609 +                else {
  37.610 +                    pgp_key_free(key);
  37.611 +                    key = NULL;
  37.612 +                    missing_pass = true;
  37.613 +                    continue;
  37.614 +                }
  37.615 +            }
  37.616 +        }
  37.617 +        if (!key) {
  37.618 +            if (bad_pass)
  37.619 +                ERROR_OUT(err, PEP_WRONG_PASSPHRASE, "pgp_key_decrypt_secret");
  37.620 +            else if (missing_pass)    
  37.621 +                ERROR_OUT(err, PEP_PASSPHRASE_REQUIRED, "pgp_key_decrypt_secret");
  37.622 +            else        
  37.623 +                ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_valid_key_amalgamation_key");            
  37.624 +        }
  37.625 +                
  37.626 +                    
  37.627          signing_keypair = pgp_key_into_key_pair (NULL, pgp_key_clone (key));
  37.628          pgp_key_free (key);
  37.629          if (! signing_keypair)
  37.630 @@ -2004,7 +2229,7 @@
  37.631      *ctext = t;
  37.632      (*ctext)[*csize] = 0;
  37.633  
  37.634 - out:
  37.635 + out:    
  37.636      pgp_signer_free (signer);
  37.637      // XXX: pgp_key_pair_as_signer is only supposed to reference
  37.638      // signing_keypair, but it consumes it.  If this is fixed, this
  37.639 @@ -2045,6 +2270,55 @@
  37.640          psize, ctext, csize, true);
  37.641  }
  37.642  
  37.643 +static char* _filter_parentheses(const char* input) {
  37.644 +    if (!input)
  37.645 +        return NULL;
  37.646 +    
  37.647 +    int input_len = strlen(input) + 1;
  37.648 +    char* retval = calloc(input_len, 1);
  37.649 +    strlcpy(retval, input, input_len);
  37.650 +
  37.651 +    char* curr_c;
  37.652 +    
  37.653 +    for (curr_c = retval; curr_c && *curr_c != '\0'; curr_c++) {
  37.654 +        switch(*curr_c) {
  37.655 +            case '(':
  37.656 +                *curr_c = '[';
  37.657 +                break;
  37.658 +            case ')':
  37.659 +                *curr_c = ']';
  37.660 +                break;
  37.661 +            default:
  37.662 +                break;
  37.663 +        }
  37.664 +    }  
  37.665 +    
  37.666 +    return retval;
  37.667 +}
  37.668 +
  37.669 +static char* _flatten_to_alphanum(const char* input) {
  37.670 +    if (!input)
  37.671 +        return NULL;
  37.672 +    
  37.673 +    int input_len = strlen(input) + 1;
  37.674 +    char* retval = calloc(input_len, 1);
  37.675 +    strlcpy(retval, input, input_len);
  37.676 +
  37.677 +    char* curr_c;
  37.678 +    
  37.679 +    for (curr_c = retval; curr_c && *curr_c != '\0'; curr_c++) {
  37.680 +        char c = *curr_c;
  37.681 +
  37.682 +        if (c == ' ' || (c >= 'A' && c <= 'Z') || 
  37.683 +                        (c >= 'a' && c <= 'z') ||
  37.684 +                        (c >= '0' && c <= '9'))
  37.685 +            continue;           
  37.686 +
  37.687 +        *curr_c = '_';
  37.688 +    }  
  37.689 +    
  37.690 +    return retval;
  37.691 +}
  37.692  
  37.693  PEP_STATUS _pgp_generate_keypair(PEP_SESSION session, pEp_identity *identity, time_t when)
  37.694  {
  37.695 @@ -2062,6 +2336,11 @@
  37.696      assert(identity->fpr == NULL || identity->fpr[0] == 0);
  37.697  //    assert(identity->username);
  37.698  
  37.699 +    const char* passphrase = session->generation_passphrase;
  37.700 +
  37.701 +    if (session->new_key_pass_enable && (!passphrase || passphrase[0] == '\0'))
  37.702 +        return PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED;
  37.703 +
  37.704      char* cached_username = identity->username;
  37.705      
  37.706      if (identity->username && strcmp(identity->address, identity->username) == 0) {
  37.707 @@ -2069,11 +2348,29 @@
  37.708          identity->username = NULL;
  37.709      }
  37.710      
  37.711 +
  37.712      userid_packet = pgp_user_id_from_unchecked_address(&err,
  37.713                                                         identity->username, NULL,
  37.714                                                         identity->address);           
  37.715 +                                                   
  37.716 +    if (!userid_packet) {
  37.717 +        char* tmpname = _filter_parentheses(identity->username);
  37.718 +        userid_packet = pgp_user_id_from_unchecked_address(&err,
  37.719 +                                                           tmpname, NULL,
  37.720 +                                                           identity->address);               
  37.721 +        free(tmpname);                                                   
  37.722 +    }
  37.723 +
  37.724 +    if (!userid_packet) {
  37.725 +        char* tmpname = _flatten_to_alphanum(identity->username);
  37.726 +        userid_packet = pgp_user_id_from_unchecked_address(&err,
  37.727 +                                                           tmpname, NULL,
  37.728 +                                                           identity->address);               
  37.729 +        free(tmpname);                                                           
  37.730 +    }
  37.731 +                                            
  37.732      identity->username = cached_username;                                                   
  37.733 -
  37.734 +    
  37.735      if (!userid_packet)
  37.736          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "pgp_user_id_from_unchecked_address");
  37.737  
  37.738 @@ -2094,6 +2391,9 @@
  37.739      pgp_cert_builder_t certb = pgp_cert_builder_general_purpose(
  37.740          cipher_suite(session->cipher_suite), userid);
  37.741  
  37.742 +    if (session->new_key_pass_enable)        
  37.743 +        pgp_cert_builder_set_password(&certb, (uint8_t*)passphrase, strlen(passphrase));        
  37.744 +
  37.745      pgp_cert_builder_set_creation_time(&certb, when);
  37.746  
  37.747      pgp_signature_t rev;
  37.748 @@ -2107,7 +2407,7 @@
  37.749      pgp_fpr = pgp_cert_fingerprint(cert);
  37.750      fpr = pgp_fingerprint_to_hex(pgp_fpr);
  37.751  
  37.752 -    status = cert_save(session, cert, NULL);
  37.753 +    status = cert_save(session, cert, NULL, NULL);
  37.754      cert = NULL;
  37.755      if (status != 0)
  37.756          ERROR_OUT(NULL, PEP_CANNOT_CREATE_KEY, "saving TSK");
  37.757 @@ -2185,15 +2485,26 @@
  37.758      return retval;
  37.759   }
  37.760  
  37.761 +// This is for single keys, which is why we're using a boolean here.
  37.762  PEP_STATUS _pgp_import_keydata(PEP_SESSION session, const char *key_data,
  37.763 -                              size_t size, identity_list **private_idents)
  37.764 +                               size_t size, identity_list **private_idents,
  37.765 +                               stringlist_t** imported_keys,
  37.766 +                               uint64_t* changed_bitvec)
  37.767  {
  37.768      PEP_STATUS status = PEP_NO_KEY_IMPORTED;
  37.769      pgp_error_t err;
  37.770      pgp_cert_parser_t parser = NULL;
  37.771 +    char* issuer_fpr_hex = NULL;
  37.772 +    char* cert_fpr_hex = NULL;
  37.773 +    
  37.774 +    if (changed_bitvec && !imported_keys)
  37.775 +        return PEP_ILLEGAL_VALUE;    
  37.776  
  37.777      if (private_idents)
  37.778          *private_idents = NULL;
  37.779 +
  37.780 +    stringlist_t* _import_keylist = imported_keys ? *imported_keys : NULL;    
  37.781 +    int _import_keylist_len = stringlist_length(_import_keylist);    
  37.782          
  37.783      T("parsing %zd bytes", size);
  37.784  
  37.785 @@ -2221,8 +2532,11 @@
  37.786          pgp_cert_t cert = NULL;
  37.787  
  37.788          pgp_fingerprint_t issuer_fpr = pgp_signature_issuer_fingerprint(sig);
  37.789 +        
  37.790 +        char* issuer_fpr_hex = NULL;
  37.791 +
  37.792          if (issuer_fpr) {
  37.793 -            char *issuer_fpr_hex = pgp_fingerprint_to_hex(issuer_fpr);
  37.794 +            issuer_fpr_hex = pgp_fingerprint_to_hex(issuer_fpr);
  37.795              T("Importing a signature issued by %s", issuer_fpr_hex);
  37.796  
  37.797              status = cert_find_by_fpr_hex(session, issuer_fpr_hex,
  37.798 @@ -2230,22 +2544,20 @@
  37.799              if (status && status != PEP_KEY_NOT_FOUND)
  37.800                  DUMP_ERR(NULL, status, "Looking up %s", issuer_fpr_hex);
  37.801  
  37.802 -            free(issuer_fpr_hex);
  37.803              pgp_fingerprint_free(issuer_fpr);
  37.804          }
  37.805  
  37.806          if (! cert) {
  37.807              pgp_keyid_t issuer = pgp_signature_issuer(sig);
  37.808              if (issuer) {
  37.809 -                char *issuer_hex = pgp_keyid_to_hex(issuer);
  37.810 -                T("Importing a signature issued by %s", issuer_hex);
  37.811 -
  37.812 -                status = cert_find_by_keyid_hex(session, issuer_hex,
  37.813 +                issuer_fpr_hex = pgp_keyid_to_hex(issuer);
  37.814 +                T("Importing a signature issued by %s", issuer_fpr_hex);
  37.815 +
  37.816 +                status = cert_find_by_keyid_hex(session, issuer_fpr_hex,
  37.817                                                 false, &cert, NULL);
  37.818                  if (status && status != PEP_KEY_NOT_FOUND)
  37.819 -                    DUMP_ERR(NULL, status, "Looking up %s", issuer_hex);
  37.820 -
  37.821 -                free(issuer_hex);
  37.822 +                    DUMP_ERR(NULL, status, "Looking up %s", issuer_fpr_hex);
  37.823 +
  37.824                  pgp_keyid_free(issuer);
  37.825              }
  37.826          }
  37.827 @@ -2261,7 +2573,18 @@
  37.828              if (! cert)
  37.829                  ERROR_OUT(err, PEP_UNKNOWN_ERROR, "Merging signature");
  37.830  
  37.831 -            status = cert_save(session, cert, NULL);
  37.832 +            bool changed = false;  
  37.833 +              
  37.834 +            status = cert_save(session, cert, NULL, changed_bitvec ? &changed : NULL);
  37.835 +            if (imported_keys) {
  37.836 +                if (_import_keylist)
  37.837 +                    stringlist_add(_import_keylist, issuer_fpr_hex);
  37.838 +                else 
  37.839 +                    _import_keylist = new_stringlist(issuer_fpr_hex);
  37.840 +                
  37.841 +                if (changed_bitvec && changed)
  37.842 +                    *changed_bitvec |= 1 << _import_keylist_len;
  37.843 +            }
  37.844              if (status)
  37.845                  ERROR_OUT(NULL, status, "saving merged CERT");
  37.846              status = PEP_KEY_IMPORTED;
  37.847 @@ -2274,20 +2597,38 @@
  37.848          pgp_cert_t cert;
  37.849          int count = 0;
  37.850          err = NULL;
  37.851 +        
  37.852          while ((cert = pgp_cert_parser_next(&err, parser))) {
  37.853              count ++;
  37.854  
  37.855 +            char* cert_fpr_hex = pgp_fingerprint_to_hex(pgp_cert_fingerprint(cert)); 
  37.856              T("#%d. CERT for %s, %s",
  37.857                count, pgp_cert_primary_user_id(cert, session->policy, 0),
  37.858 -              pgp_fingerprint_to_hex(pgp_cert_fingerprint(cert)));
  37.859 +              cert_fpr_hex);
  37.860  
  37.861              // If private_idents is not NULL and there is any private key
  37.862 -            // material, it will be saved.
  37.863 -            status = cert_save(session, cert, private_idents);
  37.864 -            if (status == PEP_STATUS_OK)
  37.865 +            // material, then we'll put an entry for it into private_idents 
  37.866 +            bool changed = false;
  37.867 +            status = cert_save(session, cert, private_idents, changed_bitvec ? &changed : NULL);
  37.868 +            if (status == PEP_STATUS_OK) {
  37.869                  status = PEP_KEY_IMPORTED;
  37.870 +                if (imported_keys) {
  37.871 +                    if (_import_keylist)
  37.872 +                        stringlist_add(_import_keylist, cert_fpr_hex);
  37.873 +                    else
  37.874 +                        _import_keylist = new_stringlist(cert_fpr_hex);
  37.875 +                        
  37.876 +                    if (_import_keylist_len < 64 && changed) {
  37.877 +                        *changed_bitvec |= 1 << _import_keylist_len;
  37.878 +                    }   
  37.879 +                    _import_keylist_len++;
  37.880 +                }    
  37.881 +            }    
  37.882              else
  37.883                  ERROR_OUT(NULL, status, "saving certificate");
  37.884 +            
  37.885 +            free(cert_fpr_hex);
  37.886 +            cert_fpr_hex = NULL;
  37.887          }
  37.888          if (err || count == 0)
  37.889              ERROR_OUT(err, PEP_UNKNOWN_ERROR, "parsing key data");
  37.890 @@ -2299,30 +2640,31 @@
  37.891          break;
  37.892      }
  37.893  
  37.894 -    int int_result = sqlite3_exec(
  37.895 -        session->key_db,
  37.896 -        "PRAGMA wal_checkpoint(FULL);\n"
  37.897 -        ,
  37.898 -        NULL,
  37.899 -        NULL,
  37.900 -        NULL
  37.901 -    );
  37.902 -    if (int_result != SQLITE_OK)
  37.903 -        status = PEP_UNKNOWN_DB_ERROR;
  37.904 -
  37.905   out:
  37.906      pgp_cert_parser_free(parser);
  37.907  
  37.908 +    if (imported_keys && status == PEP_KEY_IMPORTED)
  37.909 +        *imported_keys = _import_keylist;
  37.910 +    
  37.911 +    free(issuer_fpr_hex);
  37.912 +    free(cert_fpr_hex);    
  37.913 +        
  37.914      T("-> %s", pEp_status_to_string(status));
  37.915      return status;
  37.916  }
  37.917  
  37.918  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
  37.919 -                              size_t size, identity_list **private_idents)
  37.920 +                              size_t size, identity_list **private_idents,
  37.921 +                              stringlist_t** imported_keys,
  37.922 +                              uint64_t* changed_key_index)
  37.923  {
  37.924 -
  37.925 +    if (!imported_keys && changed_key_index)
  37.926 +        return PEP_ILLEGAL_VALUE;
  37.927 +        
  37.928      const char* pgp_begin = "-----BEGIN PGP";
  37.929      size_t prefix_len = strlen(pgp_begin);
  37.930 +    
  37.931 +    PEP_STATUS retval = PEP_STATUS_OK;
  37.932  
  37.933      // Because we also import binary keys we have to be careful with this.
  37.934      // 
  37.935 @@ -2336,8 +2678,11 @@
  37.936      }
  37.937  
  37.938      unsigned int keycount = count_keydata_parts(key_data, size);
  37.939 -    if (keycount < 2)
  37.940 -        return(_pgp_import_keydata(session, key_data, size, private_idents));
  37.941 +    if (keycount < 2) {
  37.942 +        retval = _pgp_import_keydata(session, key_data, size, private_idents,
  37.943 +                                     imported_keys, changed_key_index);        
  37.944 +        return retval;    
  37.945 +    }        
  37.946  
  37.947      unsigned int i;
  37.948      const char* curr_begin;
  37.949 @@ -2345,7 +2690,7 @@
  37.950  
  37.951      identity_list* collected_idents = NULL;
  37.952  
  37.953 -    PEP_STATUS retval = PEP_KEY_IMPORTED;
  37.954 +    retval = PEP_KEY_IMPORTED;
  37.955              
  37.956      for (i = 0, curr_begin = key_data; i < keycount; i++) {
  37.957          const char* next_begin = NULL;
  37.958 @@ -2361,7 +2706,12 @@
  37.959          else
  37.960              curr_size = (key_data + size) - curr_begin;
  37.961  
  37.962 -        PEP_STATUS curr_status = _pgp_import_keydata(session, curr_begin, curr_size, private_idents);
  37.963 +        PEP_STATUS curr_status = _pgp_import_keydata(session, 
  37.964 +                                                     curr_begin, 
  37.965 +                                                     curr_size, 
  37.966 +                                                     private_idents,
  37.967 +                                                     imported_keys,
  37.968 +                                                     changed_key_index);
  37.969          if (private_idents && *private_idents) {
  37.970              if (!collected_idents)
  37.971                  collected_idents = *private_idents;
  37.972 @@ -2505,7 +2855,7 @@
  37.973      bool revoked = false;
  37.974      // Don't add revoked keys to the keyinfo_list.
  37.975      if (keyinfo_list) {
  37.976 -        pgp_revocation_status_t rs = pgp_cert_revoked(cert, session->policy, 0);
  37.977 +        pgp_revocation_status_t rs = pgp_cert_revocation_status(cert, session->policy, 0);
  37.978          pgp_revocation_status_variant_t rsv = pgp_revocation_status_variant(rs);
  37.979          pgp_revocation_status_free(rs);
  37.980          if (rsv == PGP_REVOCATION_STATUS_REVOKED)
  37.981 @@ -2750,47 +3100,41 @@
  37.982      while ((ka = pgp_cert_valid_key_iter_next(key_iter, NULL, NULL))) {
  37.983          pgp_status_t sq_status;
  37.984          pgp_error_t err;
  37.985 -        pgp_packet_t *packets_tmp = NULL;
  37.986 -        size_t packet_count_tmp = 0;
  37.987 +        pgp_signature_t *sigs = NULL;
  37.988 +        size_t sig_count = 0;
  37.989  
  37.990          sq_status = pgp_valid_key_amalgamation_set_expiration_time
  37.991 -            (&err, ka, signer, t, &packets_tmp, &packet_count_tmp);
  37.992 +            (&err, ka, signer, t, &sigs, &sig_count);
  37.993          if (sq_status)
  37.994              ERROR_OUT(err, PEP_UNKNOWN_ERROR,
  37.995                        "setting expiration (generating self signatures)");
  37.996  
  37.997 -        if (! packets) {
  37.998 -            assert(packet_count == 0);
  37.999 -            assert(packet_capacity == 0);
 37.1000 -
 37.1001 -            packets = packets_tmp;
 37.1002 -            packet_count = packet_count_tmp;
 37.1003 -            packet_capacity = packet_count_tmp;
 37.1004 -        } else {
 37.1005 -            assert(packet_capacity > 0);
 37.1006 -            if (packet_capacity - packet_count < packet_count_tmp) {
 37.1007 -                // Grow the array.
 37.1008 -                int c = packet_capacity;
 37.1009 -                while (c < packet_count + packet_count_tmp) {
 37.1010 -                    c *= 2;
 37.1011 -                }
 37.1012 -
 37.1013 -                void * tmp = _pEp_reallocarray(packets, c, sizeof (*packets));
 37.1014 -                if (! tmp)
 37.1015 -                    ERROR_OUT(NULL, PEP_OUT_OF_MEMORY,
 37.1016 -                              "setting expiration (resizing buffer)");
 37.1017 -
 37.1018 -                packets = tmp;
 37.1019 -                packet_capacity = c;
 37.1020 +        if (packet_capacity - packet_count < sig_count) {
 37.1021 +            // Grow the array.
 37.1022 +            int c = packet_capacity;
 37.1023 +            if (c == 0) {
 37.1024 +                c = 1;
 37.1025              }
 37.1026 -
 37.1027 -            int i;
 37.1028 -            for (i = 0; i < packet_count_tmp; i ++) {
 37.1029 -                packets[packet_count + i] = packets_tmp[i];
 37.1030 +            while (c < packet_count + sig_count) {
 37.1031 +                c *= 2;
 37.1032              }
 37.1033 -            packet_count += packet_count_tmp;
 37.1034 +
 37.1035 +            void * tmp = _pEp_reallocarray(packets, c, sizeof (*packets));
 37.1036 +            if (! tmp)
 37.1037 +                ERROR_OUT(NULL, PEP_OUT_OF_MEMORY,
 37.1038 +                          "setting expiration (resizing buffer)");
 37.1039 +
 37.1040 +            packets = tmp;
 37.1041 +            packet_capacity = c;
 37.1042          }
 37.1043  
 37.1044 +        int i;
 37.1045 +        for (i = 0; i < sig_count; i ++) {
 37.1046 +            packets[packet_count + i] = pgp_signature_into_packet(sigs[i]);
 37.1047 +        }
 37.1048 +        packet_count += sig_count;
 37.1049 +
 37.1050 +        free (sigs);
 37.1051          pgp_valid_key_amalgamation_free (ka);
 37.1052      }
 37.1053  
 37.1054 @@ -2805,7 +3149,7 @@
 37.1055      if (! cert)
 37.1056          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration (updating cert)");
 37.1057  
 37.1058 -    status = cert_save(session, cert, NULL);
 37.1059 +    status = cert_save(session, cert, NULL, NULL);
 37.1060      cert = NULL;
 37.1061      ERROR_OUT(NULL, status, "Saving %s", fpr);
 37.1062  
 37.1063 @@ -2880,10 +3224,10 @@
 37.1064      if (! cert)
 37.1065          ERROR_OUT(err, PEP_UNKNOWN_ERROR, "setting expiration");
 37.1066  
 37.1067 -    assert(pgp_revocation_status_variant(pgp_cert_revoked(cert, session->policy, 0))
 37.1068 +    assert(pgp_revocation_status_variant(pgp_cert_revocation_status(cert, session->policy, 0))
 37.1069             == PGP_REVOCATION_STATUS_REVOKED);
 37.1070  
 37.1071 -    status = cert_save(session, cert, NULL);
 37.1072 +    status = cert_save(session, cert, NULL, NULL);
 37.1073      cert = NULL;
 37.1074      ERROR_OUT(NULL, status, "Saving %s", fpr);
 37.1075  
 37.1076 @@ -3047,7 +3391,7 @@
 37.1077  }
 37.1078  
 37.1079  static void _pgp_key_revoked(PEP_SESSION session, pgp_cert_t cert, bool* revoked) {
 37.1080 -    pgp_revocation_status_t rs = pgp_cert_revoked(cert, session->policy, 0);
 37.1081 +    pgp_revocation_status_t rs = pgp_cert_revocation_status(cert, session->policy, 0);
 37.1082      *revoked = pgp_revocation_status_variant(rs) == PGP_REVOCATION_STATUS_REVOKED;
 37.1083      pgp_revocation_status_free (rs); 
 37.1084      
 37.1085 @@ -3124,7 +3468,7 @@
 37.1086      pgp_fingerprint_free(pgp_fpr);
 37.1087      ERROR_OUT(NULL, status, "Looking up %s", fpr);
 37.1088  
 37.1089 -    // pgp_revocation_status_t rs = pgp_cert_revoked(cert, 0);
 37.1090 +    // pgp_revocation_status_t rs = pgp_cert_revocation_status(cert, 0);
 37.1091      // *revoked = pgp_revocation_status_variant(rs) == PGP_REVOCATION_STATUS_REVOKED;
 37.1092      // pgp_revocation_status_free (rs);
 37.1093      _pgp_key_revoked(session, cert, revoked);
 37.1094 @@ -3154,7 +3498,7 @@
 37.1095  
 37.1096      *comm_type = PEP_ct_OpenPGP_unconfirmed;
 37.1097  
 37.1098 -    // pgp_revocation_status_t rs = pgp_cert_revoked(cert, 0);
 37.1099 +    // pgp_revocation_status_t rs = pgp_cert_revocation_status(cert, 0);
 37.1100      // pgp_revocation_status_variant_t rsv = pgp_revocation_status_variant(rs);
 37.1101      // pgp_revocation_status_free(rs);
 37.1102      // if (rsv == PGP_REVOCATION_STATUS_REVOKED) {
    38.1 --- a/src/pgp_sequoia.h	Mon Apr 13 13:08:13 2020 +0200
    38.2 +++ b/src/pgp_sequoia.h	Tue Jul 07 11:53:12 2020 +0200
    38.3 @@ -62,7 +62,9 @@
    38.4      );
    38.5  
    38.6  PEP_STATUS pgp_import_keydata(PEP_SESSION session, const char *key_data,
    38.7 -                              size_t size, identity_list **private_idents);
    38.8 +                              size_t size, identity_list **private_idents,
    38.9 +                              stringlist_t** imported_keys,
   38.10 +                              uint64_t* changed_key_index);
   38.11  
   38.12  PEP_STATUS pgp_import_private_keydata(PEP_SESSION session, const char *key_data,
   38.13                                        size_t size, identity_list **private_idents);
    39.1 --- a/src/platform_unix.h	Mon Apr 13 13:08:13 2020 +0200
    39.2 +++ b/src/platform_unix.h	Tue Jul 07 11:53:12 2020 +0200
    39.3 @@ -23,8 +23,12 @@
    39.4  #endif
    39.5  
    39.6  #ifndef PER_MACHINE_DIRECTORY
    39.7 +#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
    39.8 +#define PER_MACHINE_DIRECTORY "/Library/Application Support/pEp"
    39.9 +#else
   39.10  #define PER_MACHINE_DIRECTORY "/usr/local/share/pEp"
   39.11  #endif
   39.12 +#endif
   39.13  
   39.14  
   39.15  #ifdef __cplusplus
    40.1 --- a/src/platform_windows.cpp	Mon Apr 13 13:08:13 2020 +0200
    40.2 +++ b/src/platform_windows.cpp	Tue Jul 07 11:53:12 2020 +0200
    40.3 @@ -147,22 +147,28 @@
    40.4          return path.c_str();
    40.5  
    40.6      TCHAR tPath[PATH_BUF_SIZE];
    40.7 +    TCHAR tPath2[PATH_BUF_SIZE];
    40.8  
    40.9      // Get SystemFolder Registry value and use if available
   40.10 -    bool result = readRegistryString(HKEY_CURRENT_USER,
   40.11 -        TEXT("SOFTWARE\\pEp"), TEXT("SystemFolder"), tPath,
   40.12 -        PATH_BUF_SIZE, NULL);
   40.13 +    bool result = readRegistryString(HKEY_CURRENT_USER, TEXT("SOFTWARE\\pEp"),
   40.14 +            TEXT("SystemFolder"), tPath2, PATH_BUF_SIZE, NULL);
   40.15  
   40.16 -    // If not Registry value was found, use default
   40.17 +    DWORD length = 0;
   40.18 +
   40.19 +    // If no Registry value was found, use default
   40.20      if (!result) {
   40.21 -        DWORD length = ExpandEnvironmentStringsW(utf16_string(string(PER_MACHINE_DIRECTORY)).c_str(),
   40.22 +        length = ExpandEnvironmentStringsW(utf16_string(string(PER_MACHINE_DIRECTORY)).c_str(),
   40.23              tPath, PATH_BUF_SIZE);
   40.24 -        assert(length);
   40.25 -        if (length == 0)
   40.26 -            throw bad_alloc(); // BUG: there are other errors possible beside out of memory
   40.27 +    }
   40.28 +    else {
   40.29 +        length = ExpandEnvironmentStringsW(tPath2, tPath, PATH_BUF_SIZE);
   40.30      }
   40.31  
   40.32 -    path = utf8_string(wstring(tPath));
   40.33 +    assert(length);
   40.34 +    if (length == 0)
   40.35 +        throw bad_alloc(); // BUG: there are other errors possible beside out of memory
   40.36 +
   40.37 +    path = utf8_string(wstring(tPath, length));
   40.38      return path.c_str();
   40.39  }
   40.40  
   40.41 @@ -173,20 +179,26 @@
   40.42          return path.c_str();
   40.43  
   40.44      TCHAR tPath[PATH_BUF_SIZE];
   40.45 +    TCHAR tPath2[PATH_BUF_SIZE];
   40.46  
   40.47      // Get UserFolder Registry value and use if available
   40.48 -    bool result = readRegistryString(HKEY_CURRENT_USER,
   40.49 -        TEXT("SOFTWARE\\pEp"), TEXT("UserFolder"), tPath,
   40.50 -        PATH_BUF_SIZE, NULL);
   40.51 +    bool result = readRegistryString(HKEY_CURRENT_USER, TEXT("SOFTWARE\\pEp"),
   40.52 +            TEXT("UserFolder"), tPath2, PATH_BUF_SIZE, NULL);
   40.53  
   40.54 -    // If not Registry value was found, use default
   40.55 +    DWORD length = 0;
   40.56 +
   40.57 +    // If no Registry value was found, use default
   40.58      if (!result) {
   40.59 -        DWORD length = ExpandEnvironmentStringsW(utf16_string(string(PER_USER_DIRECTORY)).c_str(),
   40.60 +        length = ExpandEnvironmentStringsW(utf16_string(string(PER_USER_DIRECTORY)).c_str(),
   40.61              tPath, PATH_BUF_SIZE);
   40.62 -        assert(length);
   40.63 -        if (length == 0)
   40.64 -            throw bad_alloc(); // BUG: there are other errors possible beside out of memory
   40.65      }
   40.66 +    else {
   40.67 +        length = ExpandEnvironmentStringsW(tPath2, tPath, PATH_BUF_SIZE);
   40.68 +    }
   40.69 +
   40.70 +    assert(length);
   40.71 +    if (length == 0)
   40.72 +        throw bad_alloc(); // BUG: there are other errors possible beside out of memory
   40.73  
   40.74      path = utf8_string(wstring(tPath));
   40.75      return path.c_str();
   40.76 @@ -398,7 +410,7 @@
   40.77      if (result == -1)
   40.78          return -1;
   40.79  
   40.80 -    return result + timeptr->tm_gmtoff;
   40.81 +    return (result - timeptr->tm_gmtoff);
   40.82  }
   40.83  
   40.84  void uuid_generate_random(pEpUUID out)
    41.1 --- a/src/status_to_string.h	Mon Apr 13 13:08:13 2020 +0200
    41.2 +++ b/src/status_to_string.h	Tue Jul 07 11:53:12 2020 +0200
    41.3 @@ -69,6 +69,11 @@
    41.4  
    41.5      case PEP_PHRASE_NOT_FOUND: return "PEP_PHRASE_NOT_FOUND";
    41.6  
    41.7 +    case PEP_PASSPHRASE_REQUIRED: return "PEP_PASSPHRASE_REQUIRED";
    41.8 +    case PEP_WRONG_PASSPHRASE: return "PEP_WRONG_PASSPHRASE";
    41.9 +    case PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED: return "PEP_PASSPHRASE_FOR_NEW_KEYS_REQUIRED";
   41.10 +
   41.11 +
   41.12      case PEP_SEND_FUNCTION_NOT_REGISTERED: return "PEP_SEND_FUNCTION_NOT_REGISTERED";
   41.13      case PEP_CONTRAINTS_VIOLATED: return "PEP_CONTRAINTS_VIOLATED";
   41.14      case PEP_CANNOT_ENCODE: return "PEP_CANNOT_ENCODE";
    42.1 --- a/src/sync_api.h	Mon Apr 13 13:08:13 2020 +0200
    42.2 +++ b/src/sync_api.h	Tue Jul 07 11:53:12 2020 +0200
    42.3 @@ -35,6 +35,14 @@
    42.4      // forming group
    42.5      // SYNC_NOTIFY_FORMING_GROUP = 10,
    42.6  
    42.7 +    // these two notifications must be evaluated by applications, which are
    42.8 +    // using a Desktop Adapter
    42.9 +    SYNC_NOTIFY_START = 126,
   42.10 +    SYNC_NOTIFY_STOP = 127,
   42.11 +
   42.12 +    // message cannot be sent, need passphrase
   42.13 +    SYNC_PASSPHRASE_REQUIRED = 128,
   42.14 +
   42.15      // notification of actual group status
   42.16      SYNC_NOTIFY_SOLE = 254,
   42.17      SYNC_NOTIFY_IN_GROUP = 255
   42.18 @@ -53,7 +61,7 @@
   42.19  //      PEP_STATUS_OK or any other value on error
   42.20  //
   42.21  //  caveat:
   42.22 -//      ownership of self and partner go to the callee
   42.23 +//      ownership of me and partner go to the callee
   42.24  
   42.25  typedef PEP_STATUS (*notifyHandshake_t)(
   42.26          pEp_identity *me,
    43.1 --- a/sync/cond_act_sync.yml2	Mon Apr 13 13:08:13 2020 +0200
    43.2 +++ b/sync/cond_act_sync.yml2	Tue Jul 07 11:53:12 2020 +0200
    43.3 @@ -503,15 +503,15 @@
    43.4  
    43.5      for (identity_list *_il = il; _il && _il->ident ; _il = _il->next) {
    43.6          status = set_own_key(session, _il->ident, _il->ident->fpr);
    43.7 -        if (status) {
    43.8 -            free_identity_list(il);
    43.9 -            free(user_id);
   43.10 -            return status;
   43.11 -        }
   43.12 +        if (status != PEP_STATUS_OK && status != PEP_KEY_UNSUITABLE)
   43.13 +            break;
   43.14      }
   43.15  
   43.16      free_identity_list(il);
   43.17      free(user_id);
   43.18 +
   43.19 +    if (status == PEP_KEY_UNSUITABLE)
   43.20 +        status = PEP_STATUS_OK;
   43.21  ||
   43.22  
   43.23  action useThisKey
    44.1 --- a/sync/fsm.yml2	Mon Apr 13 13:08:13 2020 +0200
    44.2 +++ b/sync/fsm.yml2	Tue Jul 07 11:53:12 2020 +0200
    44.3 @@ -49,9 +49,10 @@
    44.4  decl else;
    44.5  
    44.6  // some events have messages on the line signalling the event to the
    44.7 -// communication partner
    44.8 +// communication partner; the rate limit is in seconds until such a mesage can
    44.9 +// be repeated, 0 means off
   44.10  
   44.11 -decl message @name (id, type=anycast, security=trusted);
   44.12 +decl message @name (id, type=anycast, security=trusted, ratelimit=0);
   44.13  
   44.14  // messages can have transmitted fields…
   44.15  
    45.1 --- a/sync/gen_message_func.ysl2	Mon Apr 13 13:08:13 2020 +0200
    45.2 +++ b/sync/gen_message_func.ysl2	Tue Jul 07 11:53:12 2020 +0200
    45.3 @@ -45,6 +45,7 @@
    45.4          stringlist_t *keys;
    45.5          stringlist_t *backup;
    45.6          identity_list *identities;
    45.7 +        `` for "fsm/message[@ratelimit>0]" |>> time_t last_«../@name»_«@name»;
    45.8  
    45.9          // TIDs we're using ourselves
   45.10          `` for "func:distinctName(fsm/message/field[@type='TID'])" |>> «func:ctype()» «@name»;
    46.1 --- a/sync/gen_statemachine.ysl2	Mon Apr 13 13:08:13 2020 +0200
    46.2 +++ b/sync/gen_statemachine.ysl2	Tue Jul 07 11:53:12 2020 +0200
    46.3 @@ -412,7 +412,41 @@
    46.4                  assert(session && fsm > None && message_type > None);
    46.5                  if (!(session && fsm > None && message_type > None))
    46.6                      return PEP_ILLEGAL_VALUE;
    46.7 -                
    46.8 +            ||
    46.9 +            if "fsm/message[@ratelimit>0]" {
   46.10 +            ||
   46.11 +
   46.12 +                // test if a message with a rate limit was just sent; in case drop
   46.13 +                time_t now = time(NULL);
   46.14 +                switch (fsm) {
   46.15 +            ||
   46.16 +            for "fsm[message/@ratelimit>0]" {
   46.17 +            ||
   46.18 +                    case Sync_PR_«yml:lcase(@name)»:
   46.19 +                        switch (message_type) {
   46.20 +            ||
   46.21 +            for "message[@ratelimit>0]"
   46.22 +            ||
   46.23 +                            case «../@name»_PR_«yml:mixedCase(@name)»:
   46.24 +                                if (now < session->«yml:lcase(../../@name)»_state.own.last_«../@name»_«@name» + «@ratelimit»)
   46.25 +                                    return PEP_STATUS_OK;
   46.26 +                                break;
   46.27 +            ||
   46.28 +            ||
   46.29 +                            default:
   46.30 +                                break;
   46.31 +                        }
   46.32 +                        break;
   46.33 +            ||
   46.34 +            }
   46.35 +            ||
   46.36 +                    default:
   46.37 +                        break;
   46.38 +                }
   46.39 +            ||
   46.40 +            }
   46.41 +            ||
   46.42 +
   46.43                  «@name»_t *msg = new_«@name»_message(fsm, message_type);
   46.44                  if (!msg)
   46.45                      return PEP_OUT_OF_MEMORY;
   46.46 @@ -534,7 +568,7 @@
   46.47                      switch (message_type) {
   46.48                      `` for "fsm/message[@security='unencrypted' and ../@name!='KeySync']" | #error unencrypted only allowed with KeySync
   46.49                      `` for "fsm/message[@security='unencrypted' and ../@name='KeySync']" |>>> case «../@name»_PR_«yml:mixedCase(@name)»:
   46.50 -                            status = base_prepare_message(
   46.51 +                            status = try_base_prepare_message(
   46.52                                      session,
   46.53                                      li->ident,
   46.54                                      li->ident,
   46.55 @@ -584,7 +618,7 @@
   46.56                                  goto the_end;
   46.57                              }
   46.58  
   46.59 -                            status = encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
   46.60 +                            status = try_encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
   46.61                              if (status) {
   46.62                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   46.63                                  goto the_end;
   46.64 @@ -765,7 +799,7 @@
   46.65                              }
   46.66                              key_data = NULL;
   46.67  
   46.68 -                            status = encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
   46.69 +                            status = try_encrypt_message(session, _m, extra, &m, PEP_enc_PEP, 0);
   46.70                              if (status) {
   46.71                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   46.72                                  goto the_end;
   46.73 @@ -871,7 +905,7 @@
   46.74                              key_data = NULL;
   46.75  
   46.76                              // we do not support extra keys here and will only encrypt to ourselves
   46.77 -                            status = encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
   46.78 +                            status = try_encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
   46.79                              if (status) {
   46.80                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   46.81                                  goto the_end;
   46.82 @@ -897,7 +931,7 @@
   46.83                                  goto the_end;
   46.84                              }
   46.85  
   46.86 -                            status = encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
   46.87 +                            status = try_encrypt_message(session, _m, NULL, &m, PEP_enc_PEP, 0);
   46.88                              if (status) {
   46.89                                  status = PEP_«yml:ucase(@name)»_CANNOT_ENCRYPT;
   46.90                                  goto the_end;
   46.91 @@ -910,6 +944,37 @@
   46.92                      status = session->messageToSend(m);
   46.93                      m = NULL;
   46.94                  }
   46.95 +            ||
   46.96 +            if "fsm/message[@ratelimit>0]" {
   46.97 +            ||
   46.98 +
   46.99 +                switch (fsm) {
  46.100 +            ||
  46.101 +            for "fsm[message/@ratelimit>0]" {
  46.102 +            ||
  46.103 +                    case Sync_PR_«yml:lcase(@name)»:
  46.104 +                        switch (message_type) {
  46.105 +            ||
  46.106 +            for "message[@ratelimit>0]"
  46.107 +            ||
  46.108 +                            case «../@name»_PR_«yml:mixedCase(@name)»:
  46.109 +                                session->«yml:lcase(../../@name)»_state.own.last_«../@name»_«@name» = now;
  46.110 +                                break;
  46.111 +            ||
  46.112 +            ||
  46.113 +                            default:
  46.114 +                                break;
  46.115 +                        }
  46.116 +                        break;
  46.117 +            ||
  46.118 +            }
  46.119 +            ||
  46.120 +                    default:
  46.121 +                        break;
  46.122 +                }
  46.123 +            ||
  46.124 +            }
  46.125 +            ||
  46.126  
  46.127              the_end:
  46.128                  free_stringlist(extra);
    47.1 --- a/sync/sync.fsm	Mon Apr 13 13:08:13 2020 +0200
    47.2 +++ b/sync/sync.fsm	Tue Jul 07 11:53:12 2020 +0200
    47.3 @@ -15,8 +15,10 @@
    47.4  
    47.5          state InitState {
    47.6              on Init {
    47.7 -                if deviceGrouped
    47.8 +                if deviceGrouped {
    47.9 +                    send SynchronizeGroupKeys;
   47.10                      go Grouped;
   47.11 +                }
   47.12                  go Sole;
   47.13              }
   47.14          }
   47.15 @@ -421,12 +423,15 @@
   47.16  
   47.17          state HandshakingToJoinPhase1 {
   47.18              on Rollback {
   47.19 -                if sameNegotiation
   47.20 +                if sameNegotiation {
   47.21 +                    do untrustThisKey;
   47.22                      go Sole;
   47.23 +                }
   47.24              }
   47.25  
   47.26              on CommitReject {
   47.27                  if sameNegotiation {
   47.28 +                    do untrustThisKey;
   47.29                      do disable;
   47.30                      go End;
   47.31                  }
   47.32 @@ -531,13 +536,17 @@
   47.33              }
   47.34  
   47.35              on Rollback {
   47.36 -                if sameNegotiation
   47.37 +                if sameNegotiation {
   47.38 +                    do untrustThisKey;
   47.39                      go Grouped;
   47.40 +                }
   47.41              }
   47.42  
   47.43              on CommitReject {
   47.44 -                if sameNegotiation
   47.45 +                if sameNegotiation {
   47.46 +                    do untrustThisKey;
   47.47                      go Grouped;
   47.48 +                }
   47.49              }
   47.50  
   47.51              on CommitAccept {
   47.52 @@ -574,7 +583,7 @@
   47.53  
   47.54          // beacons are always broadcasted
   47.55  
   47.56 -        message Beacon 2, type=broadcast, security=unencrypted {
   47.57 +        message Beacon 2, type=broadcast, ratelimit=10, security=unencrypted {
   47.58              field TID challenge;
   47.59              auto Version version;
   47.60          }
   47.61 @@ -668,7 +677,7 @@
   47.62              field TID response;
   47.63          }
   47.64  
   47.65 -        message SynchronizeGroupKeys 21 {
   47.66 +        message SynchronizeGroupKeys 21, ratelimit=60 {
   47.67          }
   47.68      }
   47.69  }
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/sync/sync.md	Tue Jul 07 11:53:12 2020 +0200
    48.3 @@ -0,0 +1,664 @@
    48.4 +# p≡p KeySync
    48.5 +
    48.6 +KeySync is a protocol of the p≡p Sync family. It is defined in
    48.7 +`pEpEngine/sync/sync.fsm`.
    48.8 +
    48.9 +The Use Cases of KeySync are:
   48.10 +
   48.11 +- to discover other Devices of the same User, which are using the same Accounts
   48.12 +- to form a Device Group with these Devices
   48.13 +- to join an already existing Device Group in case of a new Device
   48.14 +- to share all Own Identities and all Own Keys within the Device Group
   48.15 +
   48.16 +## Sync Communication Channels
   48.17 +
   48.18 +p≡p Sync is designed for Communication Channels with the following properties:
   48.19 +
   48.20 +- Broadcast: any Message sent will reach all Devices
   48.21 +- Read Protected: while it is not a problem if arbitrary senders can send
   48.22 +  Messages to the Communication Channel, it must be impossible for
   48.23 +  unauthenticated Devices to read from the Channel.
   48.24 +- Offline Channel: there can be no way of deciding, which Devices are on the
   48.25 +  channel and if they're reading or not.
   48.26 +
   48.27 +Examples for Sync Communication Channels are an Inbox of an Account or an MQ
   48.28 +Topic.
   48.29 +
   48.30 +p≡p Sync is requiring at least one common Communication Channel between all
   48.31 +Devices in a Device Group.