I was mistaken.
I studied ecmodule.c a bit more, and indeed EC_POINT_add is present, although in the overloading of multiplication (and EC_POINT_MUL in the overloading of exponentiation). That's when I remembered reading somewhere in the Charm documentation that Charm was designed such that crypto equations could be written in one form irregardless of the underlying group. I.e., g**x and x*a in Zr integer group are written exactly as g**x and x*a in EC groups, although they are in fact operated as x*G and x + a in EC groups. In this way, equations would not have to be rewritten if one chooses to change the underlying groups.
In fact, I rewrote the sample code and the operations do run in EC groups as point addition and escalar-point multiplication. The rewritten sample code:
# Note that Charm overloads operators such that operations under Zr (integer) fields are written the same way as those under EC groups.
# I.e., g**x is written as is under Zr or G, but under G, it really means x*G. Likewise, a*b is written the same, but means a + b under EC groups.
# Therefore, the multiplication below is an "add" for EC points.
print("Adding Alice and Bob public keys: ", alice_public_key['y'] * bob_public_key['y'])
# Now the power here is a multiplication for EC group. Note the order; the base must come first, obviously, but it becomes the right-hand-side of the
# EC multiplication: alice_secret_key * bob_public_key
print("Multiplying Alice secret and Bob public key: ", bob_public_key['y'] ** alice_secret_key)
I have tested a few Python EC implementations and OpenSSL wrappers (pyelliptic, pyopenssl, cryptography, pycrypto), and indeed Charm has the most straightforward way of allowing for EC arithmetic: use ec_elements and just perform exponentiation and multiplication as though in Zr groups.