< sipa>
it may just work, with the existing signature
< achow101>
I'm wondering why this size makes a difference to how the signature validates
< achow101>
istm it shouldn't be covered by the signature itself
< sipa>
i believe the code signature covers the entire binary, with the signature itself wiped out (this is a guess...)
< sipa>
so its size matters
< sipa>
that would explain why a tool like codesign_allocate exists in the first place
< sipa>
as its behavior is nominal for the signing process
< achow101>
but the size of the signature isn't known until the signature is made
< sipa>
i assume that the codesign tool does now the signature size beforehand
< sipa>
*know
< sipa>
or it pads it to make sure it does
< achow101>
i suppose it just needs to fall within the page size
< achow101>
and that's probably a big enough range
< sipa>
right
< achow101>
so apple makes codesign_allocate open source, but not codesign itself?
< sipa>
apparently
< sipa>
but codesign invokes codesign_allocate
< achow101>
supposedly
< sipa>
and you can override which codesign_allocate to use... as long as it's signed by apple
< sipa>
if you run "codesign_allocate -i <gitian Bitcoin-Qt filename> -a x86_64 $((225312+1024)) -o <newname>" in linux, does the resulting binary work in macos?
< sipa>
oh, nvm
< sipa>
nope, won't work
< sipa>
that'll actually make space in the binary
< achow101>
what if I set arch to ARM64 so it uses 0x4000 as the page size?
< achow101>
and codesign_allocate doesn't like it
< sipa>
yeah i don't expect that'd work
< sipa>
achow101: but if you run codesign_allocate with 225312, on macos, you also get the 0x7c000 vmsize?
< achow101>
Ah, yes
< sipa>
so perhaps... the codesign tool isn't invoking it with size 225312
< sipa>
mayne it invokes it twice
< sipa>
once with a prospective size, to get the to-be-signed binary, and then again with the real size
< achow101>
Now, I think the installation of codesign_allocate is different from the open source one
< sipa>
that'd explain the filesize of LINKEDIT being correct, but vmsize isn't
< achow101>
Because it matches jonas's, not gitian
< sipa>
right
< sipa>
if you on linux run codesign_allocate with a larger size first, and then again withnthe correct size, does the __linkedit stuff end up being correct?
< achow101>
what's a big enough size?
< sipa>
$((225312+1024))
< achow101>
nope. also still 7b
< sipa>
after both commands, or even after the first one?
< achow101>
both
< sipa>
oh, i'm wrong
< achow101>
well both as in both both commands and first one
< sipa>
0x1000 is not 1024, but 4096
< sipa>
so $((225312+4024))
< sipa>
so $((225312+4096))
< achow101>
oh right
< achow101>
that works
< achow101>
although I will say that this is not a suitable workaround
< sipa>
we could produce in the gitian output the information on what size to resize to
< sipa>
it can be deterministically inferred from the macos-signed binary
< achow101>
i suppose
< achow101>
it feels like there should be a better way
< sipa>
yes
< sipa>
there is clearly a discrepancy between the macos codesign_allocate tool and the opensource one
< sipa>
and i'm confused why that isn't a problem for other projects
< achow101>
maybe no one has tried to make a new release recently?
< achow101>
we didn't see this a few weeks ago for rc2
< sipa>
yeah, baffling
< sipa>
lol @ actively {-beating our heads against Apple's walled garden wall-} debugging this issue
< sipa>
there is a macports version of cctools, presumably using the open source code
< sipa>
if you run that on macos, what behavior does it have?
< achow101>
it disappears eventually, but that might just mean it got moved to somewhere else
< sipa>
that one doesn't invoke codesign_allocate
< sipa>
as far i can see, but it may be in another source file
< achow101>
sipa: macports cctools uses 0x7b000
< ConsciousFlesh>
Are there any devs here who were involved with, or around when the `RPCHelpMan()` function replaced throwing a runtime error to display JSON-RPC help text?
< sipa>
achow101: great, so the apple codesign_allocate just behaves differently from their published source code
< achow101>
i guess we shouldn't be that surprised that they do different things
< achow101>
sipa: adding the run codesign_allocate twice trick to detached-sig-apply.sh does make rc3 pass signature validation
< sipa>
great
< sipa>
so we just need something to take a size from the code-signatures.tgz
< sipa>
and modify jonas' script to compute what the right pre-allocate size is
< achow101>
I wonder if maybe it would be easier to codesign_allocate the unsigned dmg with a larger than necessary but fixed sized chunk
< achow101>
the gitian signer's codesign allocate shrinks it, but I don't think effects the vmsize
< sipa>
looking at the codesign_allocate tool, it just only ever increments the vmsize
< sipa>
which is going to be the rounded-up version of the largest value the filesize ever had
< sipa>
and whatever we do, we need to replicate the apple tool's behavior
< achow101>
right, so we could always overshoot by a lot when we make the unsigned dmg
< sipa>
yup
< sipa>
that's a possibility
< luke-jr>
[20:46:44] <jonasschnelli> is there a way to speeup gitians "Upgrading system, may take a while (log in var/install.log)"? <-- I just run the base VM and update it
< achow101>
I'm going to go through history and see what the largest sigs we've had before is
< achow101>
any idea if an overly large vmsize has any negative effects?
< sipa>
i suspect if we crank up the codesign --pagesize value the sig will be much smaller
< sipa>
it signs every page separately
< achow101>
oh, is that why the sig is so big and varies a lot
< jonasschnelli>
sipa, achow101: I'm reading the backlog... for your info,... I haven't changed anything on my signing computer since signing rc2 (which was successful).
< achow101>
jonasschnelli: good to know. the backlog is quite a journey..
< jonasschnelli>
AFAIK detached-sig-create.sh under the hood, it uses the macOS codesign tool (which I haven't changed)
< jonasschnelli>
2020-12-11T23:57:47 <sipa> an alternative is making jonasschnelli downgrade his codesign_allocate tool to one that's compatible with the native_ccttols we use, and then tell his codesign tool to use that
< jonasschnelli>
^ as said,... I haven't upgraded anything since rc2
< jonasschnelli>
2020-12-12T00:12:49 <sipa> jonasschnelli: what version is your cctools? if you have the ability to change it, use 949.0.1
< jonasschnelli>
I guess sipa wants to know what clang version I have on my signing mac. Why would this be relevant? IMO codesign is not part of the llvm suite
< jonasschnelli>
And cctools on the gitian host should be irrelevant
< achow101>
cctools is separate from clang
< achow101>
it's part of xcode's developer tools
< achow101>
jonasschnelli: the tl;dr is that codesign_allocate as distributed by apple is different from codesign_allocate compiled from source
< achow101>
codesign uses codesign_allocate under the hood somewhere and that's causing us problems
< jonasschnelli>
achow101: thats very interesting...
< sipa>
jonasschnelli: can you try whag happens if you pass --pagesize 0 to the codesign tool?
< sipa>
that's unrelated, but it may result in smaller ans more predictable signature sizes
< achow101>
sipa: I've figured out what that codesign source I found doesn't have a call to codesign_allocate - the actual signing is way deeper in the stack and isn't open source. the code I found is just the wrapper to expose things as a command line tool
< jonasschnelli>
sipa: okay
< sipa>
or does it pass everything through?
< achow101>
passing extra args to detached-sig-create should pass through to codesign
< sipa>
ok
< sipa>
achow101: yeah, i tried browsing but i couldn't even find any place where the pagesize argument was used
< achow101>
I was going to suggest that we try using the macports codesign_allocate, but the manpage for codesign says "The system will not accept such substitutes unless they are specially signed (by Apple)." on that topic, so I don't think it will work
< sipa>
indeed
< sipa>
jonasschnelli: same problem?
< sipa>
achow101: is it again the vmsize being off?
< achow101>
checking
< sipa>
jonasschnelli: is that file the signed binary that comes out of the codesign tool?
< jonasschnelli>
sipa: no... that file above is the gitian signer result with using the signature.tar.gz that was built with pagesize 0
< achow101>
i need to compare against the result of the codesign tool
< sipa>
jonasschnelli: we'll also need the codesign output
< achow101>
if we combine with pagesize 0, then it'll probably always work
< achow101>
the largest signature since 0.12.1 is 407424
< sipa>
achow101: if the gitian preallocate takes it to a large *odd* multiple of 0x1000, will the macos sign tool not increase it further to a multiple of 0x2000 ?
< sipa>
if it's anything like the opensource version, it won't
< sipa>
but who knows what it does
< jonasschnelli>
oh!
< jonasschnelli>
pagesize 0 result in a valid signatue (through gitian)
< jonasschnelli>
I didn't before because I signed an already signed binary
< bitcoin-git>
bitcoin/master 5aaeb6c Russell Yanofsky: MOVEONLY: Move IsBDBFile, IsSQLiteFile, and ListWalletDir
< bitcoin-git>
bitcoin/master 6ee9cbd Russell Yanofsky: refactor: Replace ListWalletDir() function with ListDatabases()
< bitcoin-git>
bitcoin/master 6a7a636 Russell Yanofsky: refactor: Drop call to GetWalletEnv in wallet salvage code
< jonasschnelli>
I knew that when I'm going to wake up that you guys will have a solution
< achow101>
lol
< bitcoin-git>
[bitcoin] MarcoFalke merged pull request #20275: wallet: List all wallets in non-SQLite and non-BDB builds (master...pr/exist) https://github.com/bitcoin/bitcoin/pull/20275
< sipa>
achow101: number of pages, and "resources" are counted separately
< sipa>
with pagesize=0 the executable code is always 1 page
< sipa>
so i expect it to be mostly constant with pagesize=0
< jonasschnelli>
I'm also getting an invalid signature for 0.20.2rc1
< jonasschnelli>
shall I codesign with --pagesize 0?
< sipa>
jonasschnelli: that may work (50% chance)
< sipa>
jonasschnelli: basically any pagesize you try (has to be zero or a power of 2) has an independent 50% chance of being succesful with the current tooling
< sipa>
with achow's fix it should always work
< sipa>
better just wait; it can be backported too
< achow101>
Would it be worthwhile to write a tool that lets us code sign macOS from linux? Given that we can read the original code signing source, I don't think it would be too difficult to write one.
< achow101>
I don't think it's a merkle tree. I'm pretty sure it's just a flat list of hashes
< achow101>
that's what gets hashes again and signed
< wumpus>
that makes sense
< wumpus>
a hash would be much more efficient to verify per page, after all, and the signature check can be done once at load time for the hashes section
< wumpus>
per page (or bunch-of-pages) makes sense as it decreases the granularity of loading, a hash over the entire binary means the entire binary has to be read
< achow101>
so our trick to do a single page may not be ideal
< wumpus>
well if it works as a workaround
< wumpus>
but not in the long term no i guess
< achow101>
well we now know mostly how big the signature will be, so we could compute an overestimate instead
< sipa>
achow101: why not? do we care about not loading all pages all at once?
< wumpus>
if someone wants to reverse engineer this i'd prefer having a signature *verifier* first, so the gitian process can detect if it went wrong
< wumpus>
sipa: i guess so? there's always a lot of data in a binary that's not 'hot', might never be accessed at all, especially as we static link qt
< achow101>
i dunno
< achow101>
it seems like there's a default for a reason
< achow101>
and it's clearly architecture optimized
< wumpus>
that said, given the memory requiremetns i'm not sure we care about paging much
< achow101>
verification of the signature itself should only happen once
< sipa>
oh you think it's re-verifying the pages every time they get loaded again from disk
< wumpus>
yes, but the hash might be done more often, say if a page is paged out and in again?
< achow101>
I would guess this is some kind of runtime integrity check
< sipa>
that does make sense
< sipa>
but just the hash, not the full sig
< achow101>
yeah
< wumpus>
yes, the sig verification for the hashes section is likely done only once
< sipa>
but that means that the list of hashes must be loaded at all times
< wumpus>
yes
< wumpus>
so it'd be a compromise--too small page size and the list of hashes is huge, too big page size and it has very large paging granularity
< wumpus>
and i'm not sure--if it wouldn't check every time a page is re-loaded from disk it might open up some kinds of exploits, espeically for network file systems if manipulation of the data can happen without the OS knowing
< wumpus>
but that's not certain
< sipa>
if it was a Merkle tree instead they wouldn't need to keep the hash lish loaded, but it'd be twice the size
< achow101>
I think we can produce a good enough overestimate to allow for the default page size
< achow101>
slightly older version, but close enough
< achow101>
I got to SecCodeSigner::Signer::signCodeDirectory in signer.cpp before I got super lost
< phantomcircuit>
achow101, yeah that's definitely the right function
< phantomcircuit>
i got to CMSEncoderAddSigners but can't tell what it's actually doing
< phantomcircuit>
at least i think that's a decent place to look
< phantomcircuit>
also, if(hashDict != NULL) {assert(hashDict != NULL); they must not trust their compiler very much
< achow101>
CMSEncoderCopyEncodedContent claims to do the actual signing, but I find no evidence that supports that. it just kinda goes into a while function stack that I can't understand
< achow101>
*wild
< achow101>
CMSEncoderAddSigners just adds some kind of signer object to a list
< phantomcircuit>
iono kinda looks like it's actually encrypting things
< phantomcircuit>
of course there's about 10 levels of indirection though so who can even tell
< achow101>
I think it's just some more generic code that can also handle encryption?
< achow101>
honstly it's hard to know
< sipa>
for RSA encrypting and signing are kind-of interchangeable (but the devil is in the details)
< phantomcircuit>
sipa, just gotta figure out where the ciphcx object is set.. which is uhhh
< sipa>
ok, downloading xocde 10.2.1
< sipa>
*xcode
< wumpus>
can you see what hash algorithm they use? if so it might be most straightforward to check if the hashes are encrypted or otherwise obfuscating by hashing pages and looking if they appear in the signature section of the file
< wumpus>
pages are bound to have an address aligned to the start of the file, otherwise it'd be wildly inefficient
< achow101>
they use sha256, so it shouldn't be hard to check
< achow101>
The hashes are definitely embedded
< achow101>
From the 2nd page to the end of the file, the hashes in the signed binary match the unsigned one
< achow101>
the 2nd page contains the alloc thing, so it's different, but if the alloc is done, it matches
< achow101>
only the first page doesn't match. and then there are 3 "special" hashes that are of... something else
< wumpus>
achow101: oh that's great!
< achow101>
actually the first page matches, it just doesn't match the unsigned one
< wumpus>
maybe it updates something in the header first
< sipa>
well, we know it does :)
< sipa>
if it didn't, this whole problem wouldn't exist
< sipa>
the vmsize/filesize entries on the __LINKEDIT section are changed
< wumpus>
yeah then it makes sense for the hash to match the new state, not the original one
< wumpus>
right, true :)
< achow101>
yep, first 2 pages differ from unsigned because of the addition of the code signing section
< achow101>
so the hashes in the sig are 4096 byte pages from beginning of the signed binary to the beginning of the code signature
< achow101>
this is something we can verify ourselves
< sipa>
ah, neat
< achow101>
i figured out 2 of the 3 special hashes
< wumpus>
that's fast :)
< sipa>
last one may be some metadata with the signature/hashing parameters?
< achow101>
looking at the source, I think it's "entitlements"
< achow101>
but I don't know what that means
< sipa>
the codesign tool has a way to provide something called entitlements to it
< achow101>
one of the hashes is of the file Bitcoin-Qt.app/Contents/_CodeSignature/CodeResources, and the other is Bitcoin-Qt.app/Contents/Info.plist
< achow101>
but this last hash is not any of the files in the bundle
< wumpus>
if we don't pass "entitlements", maybe it's a hash of empty data?
< sipa>
if it's just some constant we don't actually care what it's a hash of
< wumpus>
right a proto-verifyer could just compare it against the fixed hash and raise alarm if it doesn't match
< achow101>
it's the same in 0.20.1, 0.21.0rc2, and 0.21.0rc3
< achow101>
afaik we don't have any entitlements so it should just be the hash of an empty something
< sipa>
google is of no help
< wumpus>
"
< wumpus>
The specific entitlements will be embedded in the signature of an application. If you are having trouble, it can help to look at what the signature actually says about the entitlements: $ codesign -d --entitlements - Example.app will show an XML property list similar to the one above.
< achow101>
it gives nothing so there are no entitlements
< wumpus>
so it's a hash of something that is in the signature itself, that sounds strange but...
< sipa>
maybe it's just <xml></xml> or something
< wumpus>
I'd expect so
< achow101>
the source code has it as a datatype of CFDataRef which I think just means it's a void *
< sipa>
wumpus: sounds similar to bitcoin's use of a sighash byte
< sipa>
part of the signature itself, and also signed
< wumpus>
sipa: ah yes
< achow101>
is there such a thing as a generic DER decoder?
< achow101>
hmm, openssl should be able to decode this if it was properly CMS DER, but it doesn't like it
< wumpus>
it apparently DiskRep::component(cdEntitlementSlot) gets the data that is hashed to verify the entitlement slot, there are different implementations of DispRep though, but in diskrep this is the file "CodeEntitlements"
< wumpus>
filediskrep*
< wumpus>
in CodeDirectory::slotIsPresent a non-zero digest in the slot means that is is present
< wumpus>
i guess i should be looking at BundleDiskRep::component(cdEntitlementSlot) as it can fetch components from the executable itself
< achow101>
I found a bunch of ASN.1 templates, this means it should be possible to figure the serialization, right?
< sipa>
achow101: can you show me the DER data?
< achow101>
sipa: in the bitcoin-detached-sigs repo osx/dist/Bitcoin-Qt.app/Contents/MacOS/Bitcoin-Qt.sign
< achow101>
that's the code signature. in theory it's DER
< achow101>
(checkout 0.21 branch)
< sipa>
you don't actually need the schema to decode DER, it's self-descriptive
< sipa>
the scheme just helps with naming stuff
< achow101>
I'm not convinced it's actually DER
< wumpus>
*i have no clue what i'm doing dog image*