Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix 582 Add support for FocusPosition in Sony RAW files #906

Merged
merged 9 commits into from
Jun 26, 2019

Conversation

clanmills
Copy link
Collaborator

@clanmills clanmills commented Jun 12, 2019

Sony2 Tag 0x9402 handler:

src/sonymn_int.hpp           TagInfo tagInfoFp(); TagInfo tagInfoFp_() ;DataBuf sonyFpCrypt(...);
src/sonymn_int.cpp           ... implementation ... 
src/tags_int.hpp             declare sony2FpId
src/tags_int.cpp             add { sony2FpId,       "Makernote", "Sony2Fp",      SonyMakerNote::tagListFp       }
src/tiffimage_int.cpp        { Tag::root, sony2FpId,        sony2Id,          0x9402    },
                             {  Tag::all, sony2FpId,        newTiffBinaryElement                      },
                             {    0x9402, sony2Id,          EXV_BINARY_ARRAY(sony2FpCfg, sony2FpDef)  },
                             extern const ArrayCfg sony2FpCfg = {
                                 sony2FpId,        // Group for the elements
                                 invalidByteOrder, // Inherit from parent
                                 ttUnsignedByte,      // Type for array entry and size element
                                 sonyFpCrypt,      // (uint16_t, const byte*, uint32_t, TiffComponent* const);
                                 false,            // No size element
                                 false,            // No fillers
                                 false,            // Don't concatenate gaps
                                 { 0, ttUnsignedByte, 1 }
                             };
                             extern const ArrayDef sony2FpDef[] = {
                                 {  0x4, ttSignedByte  , 1 }, // Exif.Sony1Fp.AmbientTemperature
                                 { 0x16, ttUnsignedByte, 1 }, // Exif.Sony1Fp.FocusMode
                                 { 0x17, ttUnsignedByte, 1 }, // Exif.Sony1Fp.AFAreaMode
                                 { 0x2d, ttUnsignedByte, 1 }  // Exif.Sony1Fp.FocusPosition2
                             };

https://sno.phy.queensu.ca/~phil/exiftool/TagNames/Sony.html#Tag9402

@clanmills clanmills added this to the v0.27.2 milestone Jun 12, 2019
@clanmills clanmills requested a review from piponazo June 12, 2019 06:57
@codecov
Copy link

Codecov bot commented Jun 12, 2019

Codecov Report

Merging #906 into 0.27-maintenance will increase coverage by 0.01%.
The diff coverage is 81.81%.

Impacted file tree graph

@@                 Coverage Diff                  @@
##           0.27-maintenance     #906      +/-   ##
====================================================
+ Coverage             62.88%   62.89%   +0.01%     
====================================================
  Files                   156      156              
  Lines                 21606    21626      +20     
====================================================
+ Hits                  13586    13602      +16     
- Misses                 8020     8024       +4
Impacted Files Coverage Δ
src/tiffimage_int.cpp 91.76% <ø> (ø) ⬆️
src/tags_int.cpp 86.41% <ø> (ø) ⬆️
src/tags_int.hpp 76.92% <ø> (ø) ⬆️
src/tiffvisitor_int.cpp 87.21% <66.66%> (-0.11%) ⬇️
src/sonymn_int.cpp 53.06% <84.21%> (+17.57%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0a47d93...d30f455. Read the comment docs.

@clanmills
Copy link
Collaborator Author

clanmills commented Jun 12, 2019

I would like to see this integrated into Exiv2 v0.27.2.1 (Exiv2 v0.27.2-RC1).

It is not presenting the correct values at present and here are the symptoms:

894 rmills@rmillsmm-local:~/gnu/github/exiv2/0.27-maintenance/build $ bin/exiv2 -pa --grep Sony2Fp ~/Andreas/test.ARW 
Exif.Sony2Fp.AmbientTemperature              Short       1  8769     == 0x2241
Exif.Sony2Fp.FocusMode                       Short       1  35980    == 0x8c8c
Exif.Sony2Fp.AFAreaMode                      Short       1  2148     == 0x0864
Exif.Sony2Fp.FocusPosition2                  Short       1  0        == 0x0000
895 rmills@rmillsmm-local:~/gnu/github/exiv2/0.27-maintenance/build $ printf "%x %x %x %x\n" 8769 35980 2148 0
2241 8c8c 864 0
896 rmills@rmillsmm-local:~/gnu/github/exiv2/0.27-maintenance/build $ dmpf ~/Andreas/real.data  | head -3
       0        0: .......X."A.....  ->  1e 01 ff 00 13 00 0a 58 0a 22 41 00 fb f2 12 00
                                                                    ***** (9&a)
    0x10       16: ..........b.....  ->  e8 0f e9 0e 00 00 06 0c 17 02 62 00 00 00 00 00
    0x20       32: ....R.R.P.P....d  ->  00 00 8b 18 52 03 52 03 50 03 50 03 8c 8c 08 64
                                                                             ***** ***** (2c)  (2e)
    //! Sony Tag 9402 Sony2Fp (FocusPosition)
    const TagInfo SonyMakerNote::tagInfoFp_[] = {
        TagInfo(  0x04, "AmbientTemperature", N_("Ambient Temperature"), N_("Ambient Temperature"), sony2FpId, makerTags,   signedByte, 1, printValue),
        TagInfo(  0x16, "FocusMode"         , N_("Focus Mode")         , N_("Focus Mode")         , sony2FpId, makerTags, unsignedByte, 1, printValue),
        TagInfo(  0x17, "AFAreaMode"        , N_("AF Area Mode")       , N_("AF Area Mode")       , sony2FpId, makerTags, unsignedByte, 1, printValue),
        TagInfo(  0x2d, "FocusPosition2"    , N_("Focus Position 2")   , N_("Focus Position 2")   , sony2FpId, makerTags, unsignedByte, 1, printValue),
        // End of list marker
        TagInfo(0xffff, "(Unknownsony2FpTag)", "(Unknownsony2FpTag)"   , "(Unknownsony2FpTag)"    , sony2FpId, makerTags, unsignedByte, 1, printValue)
    };

It appears to be decoding SHORTS from the wrong location. I've stepped the binary decoder TiffReader::visitBinaryArray() in the debugger in solving #646. I'll have to do this for Sony2Fp and fix this for v0.27.2

@clanmills clanmills self-assigned this Jun 13, 2019
@D4N D4N added the to-master label Jun 13, 2019
Copy link
Member

@D4N D4N left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks good to me and appears to do the right thing. I have however one request: can you please add an explanation to sonyFpCrypt what it does or what it should be decoding? Otherwise that function feels very much like magic.

@clanmills
Copy link
Collaborator Author

Sure, Dan. There's a great deal of discussion with Phil Harvey (ExifTool) about that function here: #582

piponazo
piponazo previously approved these changes Jun 18, 2019
Copy link
Collaborator

@piponazo piponazo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great contribution @clanmills !

I am approving already, although I made two tiny suggestions.

@@ -98,7 +98,7 @@ TABLES = Exif \
OlympusFi \
OlympusFe1 \
OlympusRi \
Panasonic \
Panasonic \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ups, this line is not aligned properly. It seems the issue is a tab character at the beginning.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. If I was granted one wish, I'd want the tab character to be made illegal in all source code, scripts, makefiles and documentation. It's a horror. An invisible character without a definition that can end up on every line of code.

}

// code byte-by-byte
uint32_t i = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[suggestion] I think that by replacing the while-loop by a for-loop the code could be reduced 2 lines.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. I've changed it.

I still have the puzzle of encoding this data which I believe is causing the .exv file to be incorrect. I will investigate that. However, let's get this PR into v0.27.2 because it's good for reading the data which is the priority for @cryptomilk

I believe sonyFpCrypt() is a symmetric encrypt/decrypt. The structure ArrayCfg has an crypt entry. However it's not clear how the function knows if it's encrypting or decrypting and I don't want to change the API.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe sonyFpCrypt() is a symmetric encrypt/decrypt

In the ExifTool Decipher() routine, the $encipher parameter is a flag which is true to reverse the direction of the cipher (ie. encipher instead of decipher the data). When you had this line of code:

code[i] = (i * i * i) % 249 ;

you were enciphering. When you switched it to this:

code[(i * i * i) % 249] = i;

you were deciphering.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's very useful, Phil. There is a bug in my implementation when I write those tags. I'm sure it's because writeMetadata() does not cipher the data. I will try to fix that now with this insight.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

YES. Thanks that's fixed the write in TiffEncoder::visitBinaryArray(). Muchy thanky.

I'll update the explanation I posted this morning to add a parameter 'decipher/encipher' to the utility sony_decipher (which will be renamed sony_cipher). Very pleased about this. Thank You very much for you help.

@mergify Mergify bot dismissed piponazo’s stale review June 20, 2019 12:19

Pull request has been modified.

piponazo
piponazo previously approved these changes Jun 20, 2019
@piponazo
Copy link
Collaborator

@clanmills do you intend to add some documentation for the sonyFpCrypt function as @D4N suggested, or is it enough with the discussion available in #582 ?

@D4N
Copy link
Member

D4N commented Jun 20, 2019

@clanmills do you intend to add some documentation for the sonyFpCrypt function as @D4N suggested, or is it enough with the discussion available in #582 ?

Please at least reference the discussion in the issue in the source code, so that next person that will touch this doesn't have to go through all the work that you guys did in #582 .

@clanmills
Copy link
Collaborator Author

Thank You @piponazo and @D4N for your thoughtful comments.

#582 is a very long discussion. I will put a summary here tomorrow and I hope you'll be happy to push this to v0.27.2. I believe we are decoding the data correctly and will please @cryptomilk.

I still have matters to investigate about re-writing this data.

@cryptomilk
Copy link
Collaborator

Yes, I'm looking forward to it :-)

@clanmills
Copy link
Collaborator Author

clanmills commented Jun 21, 2019

Andreas (@cryptomilk) provided a test file which is available on the build-server:

$ scp exiv2.dyndns.org:/Users/Shared/Jenkins/Home/userContent/testfiles/582/2018-10-17__7M34864.ARW .

Tag 0x9402 is stored in the MakerNote. It's ciphered.

$ exiftool  -v5 ~/Downloads/2018-10-17__7M34864.ARW
...
  ExifToolVersion = 11.20
  FileName = 2018-10-17__7M34864.ARW
  Directory = /Users/rmills/Downloads
  FileSize = 24972032
...
  | | | 83) Tag9402 (SubDirectory) -->
  | | |     - Tag 0x9402 (400 bytes, undef[400]):
  | | |         2f42: 6c 01 ff 00 88 00 04 d0 04 d3 e3 00 fb 9b 69 00 [l.............i.]
  | | |         2f52: 43 8a 89 05 00 00 d8 ea d7 08 dd 00 00 00 00 00 [C...............]
  | | |         2f62: 00 00 9a 81 52 1b 52 1b 38 1b 38 1b 14 14 0e 10 [....R.R.8.8.....]
  | | |         2f72: ef 10 0e 10 ef 10 e4 01 e4 01 a3 b6 00 00 00 00 [................]
  | | |         2f82: f7 18 31 41 00 00 1b 00 00 00 69 00 51 08 00 00 [..1A......i.Q...]
  | | |         2f92: 00 00 e7 00 7d 01 01 7d 95 01 00 00 01 00 6c 00 [....}..}......l.]
  | | |         2fa2: 6c 00 74 00 00 00 00 00 62 01 f6 01 ef 10 00 c4 [l.t.....b.......]
  | | |         2fb2: ff 4b 1b 9f bb 00 00 00 12 00 00 00 00 00 00 00 [.K..............]
  | | |         2fc2: 00 00 00 00 00 00 f1 00 00 00 00 00 7d 00 00 00 [............}...]
  | | |         2fd2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | |         2fe2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | |         2ff2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | |         3002: 01 00 04 56 00 00 00 00 00 00 00 00 00 00 00 00 [...V............]
  | | |         3012: 00 00 00 00 00 00 07 ea 00 00 00 00 00 00 72 c3 [..............r.]
  | | |         3022: 93 c3 76 c3 78 c3 e7 10 7a c3 7a c3 00 00 00 00 [..v.x...z.z.....]
  | | |         3032: 12 ff 40 24 00 00 00 00 00 00 00 00 00 00 7a f3 [..@$..........z.]
  | | |         3042: d2 8e dd dd dd dd 52 52 52 00 00 00 69 69 69 ea [......RRR...iii.]
  | | |         3052: 69 ea cd 00 00 70 00 00 7d 00 00 00 ff ff c6 98 [i....p..}.......]
  | | |         3062: c6 98 c6 98 68 98 c6 98 68 98 c6 98 ff ff ff ff [....h...h.......]
  | | |         3072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | |         3082: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | |         3092: 00 00 08 01 00 00 00 00 00 00 00 00 ff ff 00 18 [................]
  | | |         30a2: 0c 8a 00 00 00 00 00 00 8e 10 00 d7 00 54 29 29 [.............T))]
  | | |         30b2: 7d 01 e7 00 f1 97 8f 00 01 ff 7a f3 d2 8e 1b 00 [}.........z.....]
  | | |         30c2: 8a 00 00 00 00 01 40 00 93 10 92 00 34 00 00 00 [......@.....4...]
  | | | + [Deciphered Tag9402 directory]
  | | | |       2f42: 1e 01 ff 00 13 00 0a 58 0a 22 41 00 fb f2 12 00 [.......X."A.....]
  | | | |       2f52: e8 0f e9 0e 00 00 06 0c 17 02 62 00 00 00 00 00 [..........b.....]
  | | | |       2f62: 00 00 8b 18 52 03 52 03 50 03 50 03 8c 8c 08 64 [....R.R.P.P....d]
  | | | |       2f72: 2f 64 08 64 2f 64 8d 01 8d 01 ee 11 00 00 00 00 [/d.d/d..........]
  | | | |       2f82: c7 69 6a 5c 00 00 03 00 00 00 12 00 21 02 00 00 [.ij\........!...]
  | | | |       2f92: 00 00 09 00 05 01 01 05 20 01 00 00 01 00 1e 00 [........ .......]
  | | | |       2fa2: 1e 00 4d 00 00 00 00 00 47 01 48 01 2f 64 00 40 [..M.....G.H./d.@]
  | | | |       2fb2: ff 51 03 7e 19 00 00 00 f0 00 00 00 00 00 00 00 [.Q.~............]
  | | | |       2fc2: 00 00 00 00 00 00 f7 00 00 00 00 00 05 00 00 00 [................]
  | | | |       2fd2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       2fe2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       2ff2: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       3002: 01 00 0a 0b 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       3012: 00 00 00 00 00 00 28 0c 00 00 00 00 00 00 cf 63 [......(........c]
  | | | |       3022: 57 63 91 63 e1 63 09 64 b3 63 b3 63 00 00 00 00 [Wc.c.c.d.c.c....]
  | | | |       3032: f0 ff 04 30 00 00 00 00 00 00 00 00 00 00 b3 72 [...0...........r]
  | | | |       3042: 99 3d 62 62 62 62 52 52 52 00 00 00 12 12 12 0c [.=bbbbRRR.......]
  | | | |       3052: 12 0c 0d 00 00 10 00 00 05 00 00 00 ff ff ba 9e [................]
  | | | |       3062: ba 9e ba 9e bf 9e ba 9e bf 9e ba 9e ff ff ff ff [................]
  | | | |       3072: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       3082: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
  | | | |       3092: 00 00 02 01 00 00 00 00 00 00 00 00 ff ff 00 69 [...............i]
  | | | |       30a2: 1b 0f 00 00 00 00 00 00 3d 64 00 17 00 54 a1 a1 [........=d...T..]
  | | | |       30b2: 05 01 09 00 f7 b2 d4 00 01 ff b3 72 99 3d 03 00 [...........r.=..]
  | | | |       30c2: 0f 00 00 00 00 01 04 00 57 64 1a 00 d0 00 00 00 [........Wd......]
...

We can locate the data with exiv2 as follows:

$ exiv2 -pR ~/Downloads/2018-10-17__7M34864.ARW | grep 9402
        6308 | 0x9402                              | UNDEFINED |      400 |     12098 | l.............i.C.............. ...

And extract it with dd:

$ dd bs=1 skip=12098 if=2018-10-17__7M34864.ARW count=400  2>/dev/null | dmpf -
       0        0: l.............i.  ->  6c 01 ff 00 88 00 04 d0 04 d3 e3 00 fb 9b 69 00
    0x10       16: C...............  ->  43 8a 89 05 00 00 d8 ea d7 08 dd 00 00 00 00 00
    0x20       32: ....R.R.8.8.....  ->  00 00 9a 81 52 1b 52 1b 38 1b 38 1b 14 14 0e 10
    0x30       48: ................  ->  ef 10 0e 10 ef 10 e4 01 e4 01 a3 b6 00 00 00 00
    0x40       64: ..1A......i.Q...  ->  f7 18 31 41 00 00 1b 00 00 00 69 00 51 08 00 00
    0x50       80: ....}..}......l.  ->  00 00 e7 00 7d 01 01 7d 95 01 00 00 01 00 6c 00
    0x60       96: l.t.....b.......  ->  6c 00 74 00 00 00 00 00 62 01 f6 01 ef 10 00 c4
    0x70      112: .K..............  ->  ff 4b 1b 9f bb 00 00 00 12 00 00 00 00 00 00 00
    0x80      128: ............}...  ->  00 00 00 00 00 00 f1 00 00 00 00 00 7d 00 00 00
    0x90      144: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xa0      160: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xb0      176: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xc0      192: ...V............  ->  01 00 04 56 00 00 00 00 00 00 00 00 00 00 00 00
    0xd0      208: ..............r.  ->  00 00 00 00 00 00 07 ea 00 00 00 00 00 00 72 c3
    0xe0      224: ..v.x...z.z.....  ->  93 c3 76 c3 78 c3 e7 10 7a c3 7a c3 00 00 00 00
    0xf0      240: ..@$..........z.  ->  12 ff 40 24 00 00 00 00 00 00 00 00 00 00 7a f3
   0x100      256: ......RRR...iii.  ->  d2 8e dd dd dd dd 52 52 52 00 00 00 69 69 69 ea
   0x110      272: i....p..}.......  ->  69 ea cd 00 00 70 00 00 7d 00 00 00 ff ff c6 98
   0x120      288: ....h...h.......  ->  c6 98 c6 98 68 98 c6 98 68 98 c6 98 ff ff ff ff
   0x130      304: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x140      320: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x150      336: ................  ->  00 00 08 01 00 00 00 00 00 00 00 00 ff ff 00 18
   0x160      352: .............T))  ->  0c 8a 00 00 00 00 00 00 8e 10 00 d7 00 54 29 29
   0x170      368: }.........z.....  ->  7d 01 e7 00 f1 97 8f 00 01 ff 7a f3 d2 8e 1b 00
   0x180      384: ......@.....4...  ->  8a 00 00 00 00 01 40 00 93 10 92 00 34 00 00 00
$

We can extract and decode it with dd and sony_cipher:

$ dd bs=1 skip=12098 if=2018-10-17__7M34864.ARW count=400  2>/dev/null | ./sony_cipher decipher - - | dmpf -
       0        0: .......X."A.....  ->  1e 01 ff 00 13 00 0a 58 0a 22 41 00 fb f2 12 00
    0x10       16: ..........b.....  ->  e8 0f e9 0e 00 00 06 0c 17 02 62 00 00 00 00 00
    0x20       32: ....R.R.P.P....d  ->  00 00 8b 18 52 03 52 03 50 03 50 03 8c 8c 08 64
    0x30       48: /d.d/d..........  ->  2f 64 08 64 2f 64 8d 01 8d 01 ee 11 00 00 00 00
    0x40       64: .ij\........!...  ->  c7 69 6a 5c 00 00 03 00 00 00 12 00 21 02 00 00
    0x50       80: ........ .......  ->  00 00 09 00 05 01 01 05 20 01 00 00 01 00 1e 00
    0x60       96: ..M.....G.H./d.@  ->  1e 00 4d 00 00 00 00 00 47 01 48 01 2f 64 00 40
    0x70      112: .Q.~............  ->  ff 51 03 7e 19 00 00 00 f0 00 00 00 00 00 00 00
    0x80      128: ................  ->  00 00 00 00 00 00 f7 00 00 00 00 00 05 00 00 00
    0x90      144: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xa0      160: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xb0      176: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0xc0      192: ................  ->  01 00 0a 0b 00 00 00 00 00 00 00 00 00 00 00 00
    0xd0      208: ......(........c  ->  00 00 00 00 00 00 28 0c 00 00 00 00 00 00 cf 63
    0xe0      224: Wc.c.c.d.c.c....  ->  57 63 91 63 e1 63 09 64 b3 63 b3 63 00 00 00 00
    0xf0      240: ...0...........r  ->  f0 ff 04 30 00 00 00 00 00 00 00 00 00 00 b3 72
   0x100      256: .=bbbbRRR.......  ->  99 3d 62 62 62 62 52 52 52 00 00 00 12 12 12 0c
   0x110      272: ................  ->  12 0c 0d 00 00 10 00 00 05 00 00 00 ff ff ba 9e
   0x120      288: ................  ->  ba 9e ba 9e bf 9e ba 9e bf 9e ba 9e ff ff ff ff
   0x130      304: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x140      320: ................  ->  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x150      336: ...............i  ->  00 00 02 01 00 00 00 00 00 00 00 00 ff ff 00 69
   0x160      352: ........=d...T..  ->  1b 0f 00 00 00 00 00 00 3d 64 00 17 00 54 a1 a1
   0x170      368: ...........r.=..  ->  05 01 09 00 f7 b2 d4 00 01 ff b3 72 99 3d 03 00
   0x180      384: ........Wd......  ->  0f 00 00 00 00 01 04 00 57 64 1a 00 d0 00 00 00
$

And of course decifer/encipher get you back to where you started:

$ dd bs=1 skip=12098 if=2018-10-17__7M34864.ARW count=400  2>/dev/null | dmpf - | head -3
       0        0: l.............i.  ->  6c 01 ff 00 88 00 04 d0 04 d3 e3 00 fb 9b 69 00
    0x10       16: C...............  ->  43 8a 89 05 00 00 d8 ea d7 08 dd 00 00 00 00 00
    0x20       32: ....R.R.8.8.....  ->  00 00 9a 81 52 1b 52 1b 38 1b 38 1b 14 14 0e 10
$ dd bs=1 skip=12098 if=2018-10-17__7M34864.ARW count=400  2>/dev/null | ./sony_cipher decipher - - | ./sony_cipher encipher - - | dmpf - | head -3
       0        0: l.............i.  ->  6c 01 ff 00 88 00 04 d0 04 d3 e3 00 fb 9b 69 00
    0x10       16: C...............  ->  43 8a 89 05 00 00 d8 ea d7 08 dd 00 00 00 00 00
    0x20       32: ....R.R.8.8.....  ->  00 00 9a 81 52 1b 52 1b 38 1b 38 1b 14 14 0e 10
$

The code for sony_cipher.cpp is:

#include <iostream>
#include <stdio.h>

/*
#------------------------------------------------------------------------------
# Decipher/encipher Sony tag 0x94xx data (ref PH)
# Inputs: 0) data reference, 1) true to encipher the data
sub Decipher($;$)
{
    my ($dataPt, $encipher) = @_;
    # This is a simple substitution cipher, so use a hardcoded translation table for speed.
    # The formula is: $c = ($b*$b*$b) % 249, where $c is the enciphered data byte
    # (note that bytes with values 249-255 are not translated, and 0-1, 82-84,
    #  165-167 and 248 have the same enciphered value)
    if ($encipher) {    # encipher
        $$dataPt =~ tr/\x02-\xf7/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\...;
    } else {            # decipher
        $$dataPt =~ tr/\x08\x1b\x40\x7d\xd8\x5e\x0e\xe7\x04V\xea\xcd\x05\x8ap\...;
    }
}
*/
#define byte unsigned char
void sony_cipher(byte* bytes, int size, byte* result, bool bDecipher)
{
    // initialize the code table
    byte  code[256];
    for ( uint32_t i = 0 ; i < 249 ; i++ ) {
        if ( bDecipher ) {
            code[(i * i * i) % 249] = i ;
        } else {
            code[i] = (i * i * i) % 249 ;
        }
    }
    for ( uint32_t i = 249 ; i < 256 ; i++ ) {
        code[i] = i;
    }

    // code byte-by-byte
    for ( uint32_t i = 0 ; i < size ; i++ ) {
        result[i] = code[bytes[i]];
    }
}

int main(int argc, const char* argv[])
{
    bool bDecipher = true     ;
    bool bArgsOK   = argc == 4 ;
    if ( bArgsOK ) {
        if (         strcmp(argv[1],"decipher") == 0 ) {
             bDecipher = true ;
        } else if (  strcmp(argv[1],"encipher") == 0 ) {
             bDecipher = false ;
        } else {
             bArgsOK = false;
        }
    }

    if ( !bArgsOK  ) {
        std::cout << "syntax: " << argv[0] << " [decifer|encifer] in-file out-file" << std::endl;
    } else {
        FILE* in  = strcmp(argv[2],"-")==0 ? stdin  : fopen(argv[2],"r");
        FILE* out = strcmp(argv[3],"-")==0 ? stdout : fopen(argv[3],"w");
        if ( in && out ) {
            byte  buffer[8000];
            int   size   = fread(buffer,1,8000,in);
            byte* result = (byte*) ::malloc(size);
            sony_cipher(buffer,size,result,bDecipher);
            fwrite(result,1,size,out);
            ::free(result);
        } else {
            if ( !in  ) std::cout << "unable to open input file "  << argv[1] << std::endl;
            if ( !out ) std::cout << "unable to open output file " << argv[2] << std::endl;
        }
        if ( in  ) if (  in != stdin  ) fclose( in);
        if ( out ) if ( out != stdout ) fclose(out);
    }

    return 0;
}

The code for dmpf.cpp (my homemade file dump utility):

#include <stdio.h>
#include <string.h>

static enum
{   errorOK = 0
,   errorSyntax
,   errorProcessing
} error = errorOK ;

void syntax()
{
    printf("syntax: dmpf [-option]+ filename\n") ;
}

bool printable(unsigned char c) { return c >= 32 && c < 127 && c != '.' ; }

int main(int argc, char* argv[])
{
    char* filename = argv[1] ;
    FILE* f = NULL ;

    if ( argc < 2 ) {
        syntax() ;
        error = errorSyntax ;
    }

    if ( !error ) {
        f = strcmp(filename,"-") ? fopen(filename,"rb") : stdin ;
        if ( !f ) {
            printf("unable to open file %s\n",filename) ;
            error = errorProcessing ;
        }
    }

    if ( !error  )
    {
        char line[1000] ;
        char buff[16]   ;
        int  n          ;
        int count = 0   ;
        while ( (n = fread(buff,1,sizeof buff,f)) > 0 )
        {
            // line number
            int l = sprintf(line,"%#8x %8d: ",count,count ) ;
            count += n ;

            // ascii print
            for ( int i = 0 ; i < n ; i++ )
            {
                char c = buff[i] ;
                l += sprintf(line+l,"%c", printable(c) ? c : '.' ) ;
            }
            // blank pad the ascii
            int save = n ;
            while ( n++ < sizeof(buff) ) l += sprintf(line+l," ") ;
            n = save     ;

            // hex code
            l += sprintf(line+l,"  -> ") ;
            for ( int i = 0 ; i < n ; i++ )
            {
                unsigned char c = buff[i] ;
                l += sprintf(line+l," %02x" ,c) ;
            }

            line[l] = 0 ;
            printf("%s\n",line) ;
        }
    }

    return error ;
}

If you want to know how Phil Harvey (@boardhead) discovered the sony_cipher() function, let's discuss this with him and @cryptomilk over a beer in Rennes in 2020 #911

@cryptomilk
Copy link
Collaborator

cryptomilk commented Jun 21, 2019

Do you have access to https://raw.pixls.us/ ? If not you should talk to Pat or Mica to get access.

@clanmills
Copy link
Collaborator Author

Sure. I know Pat quite well. I met him at LGM in London and he helped a lot when I gave a presentation about Exiv2 in Rio in 2017. Very nice guy. Would like to visit him and his family one day in Alabama.

When I make releases of Exiv2, I announce them on Facebook and Pixls. If you have suggestions about other places on which to make announcements, I'll be happy to update our release procedure to include them.

I know that the Pixls community have an archive of raw files. One day we'll integrate that into our test suite.

@boardhead
Copy link
Collaborator

Robin wrote:

Tag 0x9402 is stored in the MakerNote. It's encrypted.

I suggest using the term "enciphered" for this tag. Sony has other tags which use a true (and very different) encryption. To avoid confusion, I reserve the word "encrypted" for these.

  • Phil

@clanmills
Copy link
Collaborator Author

clanmills commented Jun 21, 2019

@boardhead Thanks. I've updated the comment I posted earlier today AND updated the PR to rename the function sonyTagDecipher(). I realise from your code that there are other sony tags using the same deciphering function, so I've used a function name that is less associated with the FocusPosition tag.

@mergify Mergify bot dismissed piponazo’s stale review June 21, 2019 14:38

Pull request has been modified.

piponazo
piponazo previously approved these changes Jun 22, 2019
@clanmills clanmills requested a review from D4N June 24, 2019 17:45
@mergify Mergify bot dismissed piponazo’s stale review June 25, 2019 21:30

Pull request has been modified.


}; // class SonyMakerNote

DataBuf sonyTagCipher (uint16_t, const byte*, uint32_t, TiffComponent* const, bool bCipher);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function can very well be static in the .cpp, couldn't it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right, it could be static. It started of life as a single decipher function and grown. sonyTagCipher does not need to be visible outside of sonymn_int.cpp.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to update the PR to be sure sonyTagCipher() doesn't end up in visible symbols. I think you'll have to approve that change. I understand what "squashing commits" does, however I've never done it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2335 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance/build $ nm -g --demangle lib/libexiv2.0.27.2.1.dylib | grep sonyTag
00000000001c75a0 T Exiv2::Internal::sonyTagCipher(unsigned short, unsigned char const*, unsigned int, Exiv2::Internal::TiffComponent*, bool)
00000000001c77b0 T Exiv2::Internal::sonyTagDecipher(unsigned short, unsigned char const*, unsigned int, Exiv2::Internal::TiffComponent*)
00000000001c7890 T Exiv2::Internal::sonyTagEncipher(unsigned short, unsigned char const*, unsigned int, Exiv2::Internal::TiffComponent*)
2336 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance/build $ ce ../src/sonymn_int.cpp 
bbedit "../src/sonymn_int.cpp"

2337 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance/build $ make
[ 10%] Built target exiv2-xmp
...
2338 rmills@rmillsmbp:~/gnu/github/exiv2/0.27-maintenance/build $ nm -g --demangle lib/libexiv2.0.27.2.1.dylib | grep sonyTag
00000000001c75a0 T Exiv2::Internal::sonyTagDecipher(unsigned short, unsigned char const*, unsigned int, Exiv2::Internal::TiffComponent*)
00000000001c7890 T Exiv2::Internal::sonyTagEncipher(unsigned short, unsigned char const*, unsigned int, Exiv2::Internal::TiffComponent*)

Copy link
Collaborator

@piponazo piponazo Jun 26, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Robin, you did not push that change yet, right?

D4N
D4N previously approved these changes Jun 25, 2019
Copy link
Member

@D4N D4N left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Please squash everything before merging (or use sqash+merge on Github).

@mergify Mergify bot dismissed D4N’s stale review June 26, 2019 09:04

Pull request has been modified.

Copy link
Member

@D4N D4N left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for fixing this!

@D4N D4N merged commit ab375fb into 0.27-maintenance Jun 26, 2019
Mergify bot pushed a commit that referenced this pull request Jun 26, 2019
* Fix 582 Add support for FocusPosition in Sony RAW files
* Thanks to @boardhead sonyFpCrypt() works correctly. Removed debug code. Fixed typos.
* Update doc/templates/Makefile to process Sony2Fp
* Following review by @boardhead. Renamed sonyFpCrypt() as sonyTagDecipher().
* Fixed writing the tag thanks to @boardhead explaining encipher/decipher.
  Sadly, ArrayCfg/crpyt does not know if he's encrypting/decrypting.
  I've added a sniff in TiffEncoder::visitBinaryArrayEnd to avoid changing the API.
* Added URL to discussion concerning sonyTagCipher()
* make sonyTagCipher() a static function with no external visibility.

(cherry picked from commit ab375fb)
@mergify Mergify bot deleted the fix582_sony2Fp branch June 26, 2019 19:41
@cryptomilk
Copy link
Collaborator

Awesome, thanks you!

D4N pushed a commit that referenced this pull request Jun 27, 2019
* Fix 582 Add support for FocusPosition in Sony RAW files
* Thanks to @boardhead sonyFpCrypt() works correctly. Removed debug code. Fixed typos.
* Update doc/templates/Makefile to process Sony2Fp
* Following review by @boardhead. Renamed sonyFpCrypt() as sonyTagDecipher().
* Fixed writing the tag thanks to @boardhead explaining encipher/decipher.
  Sadly, ArrayCfg/crpyt does not know if he's encrypting/decrypting.
  I've added a sniff in TiffEncoder::visitBinaryArrayEnd to avoid changing the API.
* Added URL to discussion concerning sonyTagCipher()
* make sonyTagCipher() a static function with no external visibility.

(cherry picked from commit ab375fb)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants