Skip to content

Commit

Permalink
Merge branch 'wiki' into 'master'.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpawlicki committed Jun 7, 2016
2 parents 7d162bb + b16705c commit d9d6283
Show file tree
Hide file tree
Showing 23 changed files with 5,155 additions and 0 deletions.
56 changes: 56 additions & 0 deletions ClientLog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Introduction #

Omaha can be configured to produce a log. This page provides instructions for enabling the log and locating it.

# Location #

The log file location depends on the OS.
* **Windows XP**: `C:\Documents and Settings\All Users\Application Data\Google\Update\Log`
* **Windows Vista** and **Windows 7**: `C:\ProgramData\Google\Update\Log`

# Enabling Logging on Production (opt-win) Builds #

opt-win builds, such as the Google Update builds released to the public, support a limited set of logging (`OPT_LOG` statements in the code), which is disabled by default. To enable logging on these builds, create a file called `C:\GoogleUpdate.ini` with the following contents.

```
[LoggingLevel]
LC_OPT=1
[LoggingSettings]
EnableLogging=1
```

# Enabling Logging on Debug Builds #
Non-opt builds (dbg-win and coverage-win) allow provide much more logging and have level 3 enabled for all categories by default. The default logging can be modified by specifying an override in `C:\GoogleUpdate.ini`. Below is an example that overrides the default.

```
[LoggingLevel]
LC_CORE=5
LC_NET=4
LC_PLUGIN=3
LC_SERVICE=3
LC_SETUP=3
LC_SHELL=3
LC_UTIL=3
LC_OPT=3
LC_REPORT=3
[LoggingSettings]
EnableLogging=1
LogFilePath="C:\foo\GoogleUpdate.log"
MaxLogFileSize=10000000
ShowTime=1
LogToFile=1
AppendToFile=1
LogToStdOut=0
LogToOutputDebug=1
[DebugSettings]
SkipServerReport=1
NoSendDumpToServer=1
NoSendStackToServer=1
```
# Log Size Limits #
Omaha tries to archive the log when the log size is greater than 10 MB. When the log is in use by more than one instance of Omaha the archiving operation will fail. However, there is a 100 MB limit to how big the log can be to prevent overfilling the hard drive. When this limit is reached the log file is cleared and the logging starts from the beginning.
1 change: 1 addition & 0 deletions ClientUpdateProtocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The design doc for the Client Update Protocol (CUP) used to securely provide update information over HTTP is available at http://omaha.googlecode.com/svn/wiki/cup.html.
77 changes: 77 additions & 0 deletions ClientUpdateProtocolEcdsa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Introduction #

Starting in 2014, Omaha contains support for an alternate CUP protocol that uses ECDSA signatures for message verification instead of HMAC signatures with a RSA-encrypted key.

It can be used along side the original CUP, or as a complete replacement for it.

# Objectives #

The objective of CUP-ECDSA is similar to that of the original CUP:

**Goals:**
* It must provide message authenticity. MITM modification must be detected and rejected for both client requests and server responses.
* It must provide message freshness for server responses; a MITM attacker should not be able to replay an unmodified, authentic server response from a previous transaction in response to a new client request.

**Non-goals:**
* It does not need to provide privacy in communication.
* It does not need to ensure freshness in client requests; as long as update checks are idempotent, we don't care if client requests are replayed. Freshness is only crucial for server responses.
* It does not need to authenticate the client; as long as it knows the public key and follows the protocol, the server should answer.
* It does not need to implement PKI; for all uses of Omaha, only a single server is used at a time, and changes in the server key can be matched with upgrading the client Omaha to contain new public keys.

The main motivation in using CUP-ECDSA is reducing server load. The original CUP's costs are dominated by the cost of RSA encrypt/decrypt operations. Getting good server performance in CUP is critically reliant on caching common keys via HTTP cookies, allowing you to amortize the cost of RSA.

ECDSA signatures are very fast to compute, but work-intensive to verify, making them ideal for reducing load on the server.

## Key Rotation ##

The biggest danger in any system involving ECDSA is the danger of K repetition.

Computing an ECDSA signature starts with selecting a random 256-bit integer, called K. The combination of K and the public key are used to produce the first half of the signature, called R; the values of R, K, the private key, and the message digest are used to compute the other half of the signature, called S.

Because of this process, if the same value of K is chosen for two signature, both signatures will have the same value for R. If a malicious user can acquire two messages that have different bodies but identical R values, a straightforward computation yields the server's private key.

The chances of this happening are unlikely; the K value is a 256-bit number. Assuming that a good PRNG is used, and properly seeded, the probability of a collision is miniscule. However, to mitigate the potential of someone collecting enough values to find a K collision, any scheme based on ECDSA should include regular key rotations, at least once per year.

# Top-Level Description #

The server publishes an elliptic curve field/equation and a public key curve point to be used by the client.

For each request, the client assembles three components:

* The message body (the update request to be sent to the server).
* A small random number to be used as a client nonce for freshness (at least 32 bits).
* A code to identify the public key the client will use to verify this request.

The client converts the public key id and nonce to a string: the public key is converted to decimal, and the nonce to hexadecimal (lowercase a-f).

The client stores the update request XML in a buffer, in UTF-8 format; it appends the keyid/nonce string to this buffer. It calculates a SHA-256 hash of this combined buffer, which it stores for validation later. It sends the update request and the keyid/nonce string to the server. _(It can optionally send the SHA-256 hash to the server as well; this is not necessary for proper operation of the protocol, but can be useful as a debugging aid.)_

The server receives an update request XML, public key id, and nonce; it performs the same appending operation, and computes the SHA-256 hash of the received data buffer. _(If the client sent the optional hash, it checks for equality, and emits a server log message on inequality. It then discards the optional hash.)_

The server attempts to find a matching ECDSA private key for the specified public key id, returning an HTTP error if no such private key exists. Finally, it assembles the update response.

Before sending, the server stores the update response XML (also in UTF-8) in a buffer. It appends the computed SHA-256 hash of the request body+keyid+nonce to the buffer. It then calculates an ECDSA signature over that combined buffer, using the server’s private key. It sends the ECDSA signature and the response body + client hash back to the user.

The client receives the response XML, observed client hash, and ECDSA signature. It concatenates its copy of the request hash to the response XML, and attempts to verify the ECDSA signature using its public key. If the signature does not match, the client recognizes that the server response has been tampered in transit, and rejects the exchange.

The client then compares the SHA-256 hash in the response to the original hash of the request. If the hashes do not match, the client recognizes that the request has been tampered in transit, and rejects the exchange.

_(Note: The hash compare can technically happen before the ECDSA verification, as long as both happen before accepting.)_

_(Note 2: The hash compare is technically optional. The client could alternately choose to take the response XML and append its own copy of the request hash and nonce from the send; this will provide the same rejection quality. Passing the request hash with the response is a low-cost addition that allows the client to identify which of the two parts of the exchange were modified: the request, the response, or both.)_

# Mapping Protocol Components to HTTP #

The mapping is fairly similar to the original CUP. The update request will be sent as POST; the keyid, nonce, and SHA-256 hash will be transmitted as a query parameter in the URL.

The original CUP implementation used the "w=" query parameter to denote whether or not the body needs CUP validation. This can be overloaded if desired; however, using a different query parameter allows an Omaha server to support both CUP and CUP-ECDSA from a single entry point. The reference build of Omaha prefixes all CUPv2 params with “cup2.”

Formatting will be similar to CUP -- namely: “cup2key=%d:%u” where the first parameter is the keypair id, and the second is the client freshness nonce.

If the client chooses to send the optional SHA-256 hash for accidental tampering detection, it should convert it to a lowercase hexadecimal string (64 characters) and include it as a query parameter, such as “cup2hreq=...”. Use the standard hex representation for SHA-256, which is the eight 32-bit blocks written out in big-endian and concatenated.

The server should return the ECDSA signature and client SHA-256 hash in the **ETag** HTTP header:

* The signature consists of two 256-bit integers (“R” and “S”), in a ASN.1 sequence, encoded in DER; the hash is 256 bits.
* Convert the DER-encoded signature to lowercase hex. The SHA-256 hash will be standard hex representation.
* Concatenate them with a colon as a delimiter: “signature:hash”. The final ETag value will max out at 194 characters (plus \n), which is a bit long, but shouldn’t be risking the 8k limit on HTTP headers.
65 changes: 65 additions & 0 deletions CustomizingOmaha.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Introduction #

When initially checked out, the open-source Omaha builds "Google Update". Google Update communicates with Google's update servers, which **only support Google applications**.

The main difference between code compiled from this site and Google Update is the Authenticode signature and version number, and the CLSIDs of the COM objects. (To restore the original CLSIDs and build a complete Google Update clone, see the files in the official/ folder of the source.)

In order to use Omaha for your application or organization, you must customize the source code for your organization, and prevent it from conflicting with Google Update (or other forks of Omaha) on users' computers. You must also create your own update server.

# Mandatory Changes #

The following items **MUST** be changed before releasing a fork of Omaha. Preferably, make these changes as soon as you start development:

* **`omaha\main.scons`**

> Ensure that **`is_google_update_build`** is set to False, and adjust the vendor-specific constant strings. ("Google", "Update", etc.) In particular, once you have your update server functional, be sure to change the domain from google.com to your company's server.
> Most of those constant strings will be used to generate preprocessor defines, which are then used to create other internal strings -- for example, Registry locations, COM ProgIDs and cross-process mutex names -- so it is _**crucial**_ that you make these strings unique.
* **`omaha\base\const_object_names.h`**

> Modify **`kGlobalPrefix`** at the top of the file to contain your company name.
* **`omaha\base\const_goopdate.h`**

> Modify the names of the service names (examples: **`omaha_task_name_c`**, **`omaham_service_name`**, etc.) to contain your product's name.
* **`omaha\base\const_addresses.h`**

> If necessary, modify the URLs that will be used for performing update checks and returning results to match your update server's implementation.
* **`omaha\goopdate\omaha3_idl.idl`**

> Generate new GUIDs for every interface and coclass. Changing the descriptive names for them isn't a bad idea either. (Do not, however, change code-level names such as `IAppBundle` or `GoogleUpdate3UserClass`.)
* **`omaha\plugins\update\activex\update_control_idl.idl`**

> Generate new GUIDs for every interface and coclass.
* **`omaha\goopdate\resources\goopdate_dll\*.rc`**
* **`omaha\goopdate\resources\goopdateres\*.rc`**
* **`omaha\mi_exe_stub\*.rc`**

> Update each translation to reflect your company and product. Omaha stores all its localized data in a set of resource-only DLLs, one per language. (The MetaInstaller stub, on the other hand, stores a far more minimal set of translations for all languages inside its EXE.)
# Recommended Changes #

We strongly recommend making these changes before you release:

* Change the names of core executables -- `GoogleUpdate.exe`, `goopdate.dll`, `GoogleCrashHandler.exe`, and so on. (This will require changes to the SCons build scripts, to the names of EXEs in `omaha\base\constants.h`, to WiX MSI fragments, and to several unit tests.)

* Duplicate the contents of `common\omaha_customization_unittest.cc` into a new file, replace **`EXPECT_GU_STREQ()`** with **`EXPECT_STREQ()`**, and update the string literals for your fork of Omaha. Do the same with **`EXPECT_GU_ID_EQ()`** in a copy of `goopdate\omaha_customization_goopdate_apis_unittest.cc`. (These macros change their behavior based on the value of `is_google_update_build` in `main.scons`. When set to `True`, this test checks for equality - i.e. that the values haven't changed between builds. When set to `False`, it checks for inequality - i.e. it ensures that these values do not collide with the official Google Update releases. By adding additional tests with the first behavior, you can provide the same safety measures for your own fork.)

* Define a new CUP public key if you plan to use the CUP protocol on your update server.

* If your product exposes any settings that are controlled via Group Policy, you may want to move the Omaha GPO settings to the same location as your product. This is set in `omaha\common\const_group_policy.h`.

* Change the value of the reference GUID used to identify your fork of Omaha when self-updating. This is defined in **`kGoopdateGuid`** and **`GOOPDATE_APP_ID`** in `omaha\base\constants.h` and verified in several unit tests.

* Do a general search for strings that reference Google or Google Update, and revise them. This should include debug logging statements.

# Versioning #

The version number stored in all outputs is set in the file **`omaha\VERSION`**. Omaha has some functionality in it from Google Update related to bug workarounds when upgrading from prior versions, so don't set the VERSION to any lower than 1.3.23.0.

When releasing your fork of Omaha, we recommend starting the version at 1.3.25.0. Remember to bump the version up whenever releasing an updated version.
Loading

0 comments on commit d9d6283

Please sign in to comment.