Hi, Steve M! I've been reading your replies as you write them, and I'd like to thank you for taking so much time and addressing my concerns. I must say, however, that I'm actually less confused (having read this one) than I was before. (replies inline)
On Dec 12, 2007 5:38 AM, Steve Marquess <[EMAIL PROTECTED]> wrote: > > The module boundary is *the* key concept for FIPS 140-2. It is also a > very elusive concept in the context of software libraries -- like > pornography ("I know it when I see it") or the blind men meeting an > elephant, everyone seems to have some notion of what is is but can't > clearly articulate it. I thought I understood it five years ago, now > it's more of a puzzle to me than ever. Here's my own personal > perspective on some of the pieces to that puzzle. Since the term > "module" means something different here than for software engineering I > capitalize it in the following: > > 1) The "Module boundary" concept dates from the time when cryptography > was done entirely in hardware. The Module boundary for hardware is the > metal enclosure for the hardware device (or the circuit board for a > backplane device). The buttons and switches on the case and the wires > leading into it are the interface. Easy enough to grasp so far. When > you start talking about software running on a modern multi-tasking, > virtual memory computer it gets confusing. Okay... this makes sense, if you look at it from this perspective: I think that much of the confusion dates from higher-ranking infosec people (primarily military and/or NSA) trying to use their understandings from many years before to design the requirements for FIPS 140. Multi-tasking, virtual-memory computer systems weren't even dreamed of way back when these people learned How Cryptography Works[tm], so they couldn't dream of how it'd work. (With my fairly-pessimistic view of how these people think, I'm actually fairly surprised that they allowed FIPS validation for software at all running on anything less than an old Orange Book class "B" rated system -- mandatory access controls.) > 2) There is the "Module boundary" (the most commonly heard term). But, > you will also hear "algorithm boundary", "physical boundary", and > "logical boundary". None of those terms are entirely synonymous. My > best understanding is that the algorithm boundaries are entirely > subsumed within the generic Module boundary, the logical boundary is > kinda sorta the same as the Module boundary for a running process, the > physical boundary is roughly equivalent to an idealized computer > representative of the one used for the validation testing. But, I've > seen all these terms used in contexts that leave me wondering. I'll go out on a limb here and express my (certainly naive) extrapolations/interpolations: Module Boundary: That which contains the entire deliverable that implements the algorithms required by FIPS 140-2 and the glue to make them accessible. (The physical string of bits.) This should contain the smallest amount of code/data possibly required to fulfill the requirements of FIPS 140. Algorithm Boundary: Once you get past the "glue" which makes it possible to interface, algorithms should be completely self-contained and not reuse code -- and the algorithm shouldn't be 'steppable', meaning you call the function with the data and it gives you the transformed data', with no intermediary results. Logical Boundary: The API, behind which you should not have any visibility. (the logical boundary for UNIX is the point at which the kernel ends and the user process begins -- to the process, it doesn't need to know how the kernel does things, as long as it can know what the kernel will do when it's called.) The concept of the "logical boundary" isn't quite so far-fetched -- if you look at a chip, the logical boundary is the same as the physical boundary. With virtualization, it's necessary to define what the boundary actually does, and then find or define a point which performs the same essential functionality as the physical boundary. For physical chips, it's the data pulses applied to the chip to request that it perform a given task. For software modules, it's the calls to the library functions. Again, these are my (probably incredibly naive) views. My lack of knowledge is why I asked for the formal specification of what qualities the boundary must enforce. > 3) For software Modules the integrity test (a digest check) is performed > over the contents of the Module. Well, sort of. There are two > acceptable techniques that I know of. One is to create the software as > a runtime binary file (typically a shared library file for a crypto > library, or a standalone application program) and call the file itself > as it resides on disk the crypto Module. In this case the Module is one > contiguous string of bits, note that string of bits includes "glue" data > for the run-time loader. The reference digest value itself can't be > included in that file, of course, so it is placed in a separate file. > The second technique is to perform the digest over the text (machine > code) and read-only data segments of the program as mapped into memory > by the run-time loader. In this case the Module is two (or more) > separate contiguous strings of bits in memory (or memory mapped disk > sectors). Those reference digest values can be embedded in the runtime > binary file, outside of the Module boundary. The first technique is what OpenSSL uses to distribute the code. (The security policy defines the keyed hash that the code must match before it can be built.) The second is what OpenSSL uses to embed the code. > 4) The Module boundary is *not* every location the program counter > visits during the execution of the code between the call to and return > from a function in the Module. That program counter will traverse code > in the text segment(s) -- definitely in the boundary. It will also > traverse code in system (kernel) calls -- definitely *outside* the > boundary. It will traverse code in userspace shared libraries, and here > it gets really fuzzy. Calls from the Module to "standard system library > functions" are ok, those libraries are not considered internal to the > boundary. So libc, for example, is not in the boundary. The malloc > functions are not, most interesting (because they export the CSPs -- > secrets -- that are supposed to remain in the boundary). What exactly > is a "standard system library"? Good question. Is /usr/lib/libc.so? > Certainly! Is /usr/lib/libssl.so, which is provided by many vendors as > part of the base operating system distribution, such a libary? > Certainly not! Is /usr/lib/libncurses.so? /usr/lib/libm.so? > /usr/lib/libstdc++.so? Who knows? The term "cryptographically > significant" will arise in these discussions. I won't even pretend to > understand that term, that's one for scripture interpretation. Another (incredibly naive) view: "Cryptographically Significant": anything that Eve or Mallory could use in an attack. This includes things to spy on the running state of the cryptographic process, and things to change the running state of the cryptographic process. (This also includes the 'glue'... i.e., how to get the data into the structures necessary for the modules to operate on. This would be a prime place to make such an attack.) By that definition, malloc and friends are cryptographically significant. (An alternative would be to implement a private allocator, and build its pool through calls to the operating system itself via GlobalAlloc() (on Windows) or whatever UNIX "I want to allocate a region of memory" API exists in section 2 of the manual.) However, since the implementation of malloc and friends is generally provided by the operating system, the fact that the OS doesn't enforce intra-process memory access via credentials is something that the FIPS validation generally must recognize as "outside the module's control". What's fuzzy, though, is "can I implement my own malloc and have it be able to be used by the FIPS module and have what I've implemented retain its FIPS validation?" Based on what you wrote above, I'm pretty sure the answer should be 'no' -- and my software implementation should also lose validation if there's anything that is LD_PRELOADed that overrides malloc. > 5) Physical consanguinity within the Module boundary is significant. By > this I mean that the sequence of machine instructions and read-only data > that comprise the code of the Module must always occur in a fixed > relationship with respect to ascending memory addresses. When a > build-time linker (ld) creates an executable binary from an archive > library containing the object modules, A, B, C, it doesn't much care > what order (in terms of ascending memory addresses) they appear in the > output file; A-B-C, B-C-A, etc. Even though the resulting executables > are functionally identical that is not acceptable for a FIPS 140-2 > Module, the runtime code must be guaranteed to be in the same sequence > (this requirement inspired the fipscanister.o "monolithic" object module). Ah, that's information I didn't have. The design of fipscanister.o makes a lot more sense now. > 6) The digest does more than merely verify that the Module code has not > been corrupted. It also existentially defines the Module. We > encountered a specific requirement that the digest *cannot* cover any > code not properly part of the Module. Specifically, if you want your > Module to be a single runtime executable containing the three crypto > related object modules A,B,C and the unrealted modules X,Y,Z, the > resulting linked program containing the object modules A,B,C,X,Y,Z > cannot be defined as the Module. The digest over all six object modules > will of course verify that A,B,C have not been corrupted, but including > X,Y,Z in that digest is not allowed. Instead the digest must cover > A,B,C only. The fipscanister.o monolithic object modules addresses this > requirement as well. That's the first time I've heard the term 'existential' in relation to a piece of software. :) This requirement makes sense, as far as the "hardware module that can now exist in virtual address space" idea goes... because if you have a piece of memory where you can say "This is where all of my cryptographic code is implemented", they (as in 'auditors') must be able to create the digest and verify it against what it's supposed to be. (The same way they're supposed to be able to look at chips and say "yes, this is valid".) > If you're confused now, welcome to the club. The confusion exists from logical extrapolation of the specification in ways that seem to conflict with each other by many different people over many years. The specs themselves could use an overhaul, with these issues in-mind. The chances of that happening, though, are nil. Unless someone wants to lobby Congress or the NIST. Thank you again for your time and your answers! -Kyle H ______________________________________________________________________ OpenSSL Project http://www.openssl.org Development Mailing List openssl-dev@openssl.org Automated List Manager [EMAIL PROTECTED]